BASH e comportamento de retorno de carro

7

Eu tenho uma pergunta rápida.
É normal que bash (eu estou usando 4.4.11) não está exibindo linhas / texto que é separado / final com% normal\r?

Fiquei um pouco surpreso ao ver esse comportamento:

$ a=$(printf "hello\ragain\rgeorge\r\n")
$ echo "$a"
george

Mas o texto "Olá novamente" ainda está lá, de alguma forma "oculto":

$ 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

E assim que jogarmos com o bash, tudo bem .... Mas isso é um risco de segurança em potencial? E se o conteúdo da variável "a" vier do mundo externo e incluir "comandos ruins" em vez de apenas oi?

Outro teste, um pouco inseguro desta vez:

$ 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>

Imagine um rm oculto em vez de um ls oculto.

O mesmo comportamento ao usar echo -e:

$ a=$(echo -e "ls;\rGeorge\r\n"); echo "$a"
George

Sou eu que faz algo errado ...?

    
por George Vasiliou 03.04.2017 / 11:13

3 respostas

16

Seu echo "$a" imprime "olá", depois volta para o início da linha (que é o que \r faz), imprime "novamente", volta novamente, imprime "george", volta novamente e vai para a próxima linha ( \n ). É tudo perfeitamente normal, mas como chepner aponta, isso não tem nada a ver com o Bash: \r e \n são interpretados pelo terminal, não pelo Bash (é por isso que você obtém a saída completa quando canaliza o comando para od ).

Você pode ver isso melhor com

$ a=$(printf "hellooooo\r  again,\rgeorge\r\n")
$ echo "$a"

pois isso deixará o fim do texto sobrescrito:

georgen,o

Você não pode realmente usar isso para ocultar comandos, apenas a saída deles (e somente se você pode sobrescrever com caracteres suficientes), a menos que use eval conforme mostrado (mas usar eval geralmente não é recomendado). Um truque mais perigoso é usar usando CSS para mascarar comandos destinados a serem copiados e colados de sites da Web.

    
por 03.04.2017 / 11:17
3

No mundo Unix, um retorno de carro (comumente codificado como \r nas linguagens de programação) é um controle sem marca personagem. Você pode ter retornos de carro dentro de uma linha de texto, como qualquer outro caractere além de um feed de linha (também chamado de newline ), que marca o fim de uma linha.

Em particular, em um script bash, um retorno de carro é um caractere constituinte comum de palavras, como letras e dígitos. Qualquer efeito especial do retorno do carro vem do terminal, não do shell.

Um retorno de carro é um caractere de controle . Quando você imprime em um terminal, em vez de exibir um glifo , o terminal executa algum efeito especial. Para um retorno de carro, o efeito especial é mover o cursor para o início da linha atual. Assim, se você imprimir uma linha que contenha um retorno de carro no meio, o efeito é que a segunda metade é escrita no primeiro tempo.

Vários outros caracteres de controle têm efeitos especiais: o caractere de retrocesso move o cursor para a esquerda em uma posição. O caractere da campainha faz com que o terminal emita um som ou atraia a atenção do usuário. O caractere de escape inicia uma seqüência de escape , que pode ter todos os tipos de efeitos especiais.

Se você exibir uma saída não confiável, precisará remover ou escapar caracteres de controle. Não apenas os retornos de carro, mas também vários outros, em particular o personagem de escape, que pode causar todos os tipos de efeitos ruins. Consulte É possível “cat -ing” um arquivo ser um potencial risco de segurança? e Como evitar o escape ataques sequenciais em terminais? para mais sobre o assunto.

    
por 04.04.2017 / 01:36
-1

Você pode visualizar os retornos de carro em uma variável bash usando a função printf com um formato %q .

$ TESTVAR="$(printf ' Version: 1 \r Build: 20180712 \r Test: 1324')"

$ printf %q $TESTVAR
Version:1$'\r'Build:20180712$'\r'Test:1324

Fontes e outras leituras:

por 13.07.2018 / 00:14