J'ai une petite question.
Est-il normal que bash (j'utilise 4.4.11) n'affiche pas les lignes/textes séparés/fin avec _ \r
?
J'ai été un peu surpris de voir ce comportement:
$ a=$(printf "hello\ragain\rgeorge\r\n")
$ echo "$a"
george
Mais le texte "bonjour encore" est toujours là, en quelque sorte "caché":
$ echo "$a" |od -w32 -t x1c
0000000 68 65 6c 6c 6f 0d 61 67 61 69 6e 0d 67 65 6f 72 67 65 0d 0a
h e l l o \r a g a i n \r g e o r g e \r \n
Et dès que nous jouons avec bash, c'est bien ... Mais est-ce un risque potentiel pour la sécurité? Et si le contenu de la variable "a" venait du monde extérieur et incluait de "mauvaises commandes" au lieu de juste bonjour?
Un autre test, un peu incertain cette fois:
$ a=$(printf "ls;\rGeorge\n")
$ echo "$a"
George
$ eval "$a"
0 awkprof.out event-tester.log helloworld.c oneshot.sh rightclick-tester.py tmp uinput-simple.py
<directory listing appears with an error message at the end for command George>
Imaginez un rm
caché au lieu d'un ls
caché.
Même comportement lors de l'utilisation d'écho -e:
$ a=$(echo -e "ls;\rGeorge\r\n"); echo "$a"
George
Est-ce moi qui fait quelque chose de mal ...?
Votre echo "$a"
imprime "bonjour", puis revient au début de la ligne (qui est ce que \r
fait), imprime "encore", revient en arrière, imprime "george", revient en arrière et passe à la ligne suivante (\n
). Tout est parfaitement normal, mais comme le souligne chepner , cela n'a rien à voir avec Bash: \r
et \n
sont interprétés par le terminal, pas par Bash (c'est pourquoi vous obtenez la sortie complète lorsque vous dirigez la commande vers od
).
Vous pouvez mieux voir cela avec
$ a=$(printf "hellooooo\r again,\rgeorge\r\n")
$ echo "$a"
car cela laissera la fin du texte écrasé:
georgen,o
Cependant, vous ne pouvez pas vraiment l'utiliser pour masquer les commandes, uniquement leur sortie (et uniquement si vous pouvez être sûr d'écraser avec suffisamment de caractères), à moins d'utiliser eval
comme vous le montrez (mais en utilisant eval
n'est généralement pas recommandé). Une astuce plus dangereuse est en utilisant CSS pour masquer les commandes destiné à être copié et collé à partir de sites Web.
Dans le monde Unix, un retour chariot (généralement codé comme \r
dans les langages de programmation) est un caractère de contrôle banal. Vous pouvez avoir des retours chariot à l'intérieur d'une ligne de texte, comme tout autre caractère en dehors d'un saut de ligne (également appelé nouvelle ligne ), qui marque la fin d'une ligne.
En particulier, dans un script bash, un retour chariot est un caractère constituant Word ordinaire, comme les lettres et les chiffres. Tout effet spécial du retour de transport provient du terminal et non du Shell.
Un retour chariot est un caractère de contrôle . Lorsque vous l'imprimez sur un terminal, au lieu d'afficher un glyphe , le terminal effectue un effet spécial. Pour un retour chariot, l'effet spécial est de déplacer le curseur au début de la ligne courante. Ainsi, si vous imprimez une ligne contenant un retour chariot au milieu, l'effet est que la seconde moitié est écrite sur la première moitié.
Plusieurs autres caractères de contrôle ont des effets spéciaux: le caractère de retour arrière déplace le curseur vers la gauche d'une position. Le caractère de cloche amène le terminal à émettre un son ou à attirer autrement l'attention de l'utilisateur. Le caractère d'échappement commence une séquence d'échappement qui peut avoir toutes sortes d'effets spéciaux.
Si vous affichez une sortie non approuvée, vous devez nettoyer ou échapper les caractères de contrôle. Non seulement les retours de chariot, mais aussi plusieurs autres, en particulier le caractère d'échappement, qui peuvent provoquer toutes sortes de mauvais effets. Voir Le "cat-ing" un fichier peut-il être un risque potentiel pour la sécurité? et Comment éviter les attaques de séquence d'échappement dans les terminaux? pour plus d'informations sur le sujet.
Vous pouvez afficher les retours chariot dans une variable bash en utilisant la fonction printf
avec un %q
format.
$ TESTVAR="$(printf ' Version: 1 \r Build: 20180712 \r Test: 1324')"
$ printf %q $TESTVAR
Version:1$'\r'Build:20180712$'\r'Test:1324
Sources et lectures complémentaires: