Como posso exportar o NUL corretamente para um arquivo por meio de um script?

1
$ FILE="$(mktemp)"
$ printf "a
#! /bin/bash

cmd=("$@")
FILE="$(mktemp)"
eval "${cmd[@]}" > "$FILE"
od -tx1z "$FILE"
\n" > "$FILE" $ od -tx1z "$FILE" 0000000 61 00 0a >a..< 0000003

Até aí tudo bem.

Eu envolvi o acima em um script bash

$ script printf 'a
FILE="$(mktemp)"
printf "a
$ FILE="$(mktemp)"
$ printf "a
#! /bin/bash

cmd=("$@")
FILE="$(mktemp)"
eval "${cmd[@]}" > "$FILE"
od -tx1z "$FILE"
\n" > "$FILE" $ od -tx1z "$FILE" 0000000 61 00 0a >a..< 0000003
\n" > "$FILE" S="$(uuencode -m "$FILE" /dev/stdout)" uudecode -o /dev/stdout <(printf "$S") | od -tx1 rm "$FILE"
\n' 0000000 61 30 6e >a0n< 0000003

mas

$ script printf 'a
FILE="$(mktemp)"
printf "a%pre%\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
\n' 0000000 61 30 6e >a0n< 0000003

Por que a saída muda %code% para string literal? Como posso evitar que isso aconteça?

Não é muito importante neste post: minha pergunta vem do fato de que estou tentando incluir alguns comandos em um script bash, por isso, evite um expansão de comando da remoção de NUL :

%pre%     
por Ben 20.11.2018 / 18:32

2 respostas

1

Why does the output change

I am trying to wrap some commands into a bash script, so to prevent a command expansion from removing NUL:

S="$(uuencode -m "$FILE" /dev/stdout)"
to literal string? How can I prevent that from happening?

Porque você usou eval , que adiciona outro nível de processamento de shell. eval executa o comando printf an\n , em que as contrabarras escapam do zero e o eval , deixando-as como estão com a barra invertida removida.

Você pode evitar isso, não usando "$@" > "$FILE" . Apenas usar eval deve funcionar para executar o comando fornecido como argumentos para o script. Embora nesse caso, você não pudesse usar redirecionamentos ou outras sintaxes de shell, como era possível com uuencode -m . Ou você poderia redesenhar a coisa toda para não precisar passar comandos como argumentos.

%bl0ck_qu0te%

Isso é um problema aqui? a não deve produzir bytes NUL. Exatamente o oposto, já que codifica dados binários para texto.

Esse último script grava um $FILE , um NUL e uma nova linha para od e passa o mesmo para 0000000 61 00 0a , que imprime a representação hexadecimal desses, %code% , ou algo assim. / p>     

por 20.11.2018 / 18:45
1

Você pode produzir um NUL para stdout, stderr ou recebê-lo do stdin.
Qualquer " captura" interna e (quase) qualquer uso de uma NUL é um problema.

Você pode emitir um NUL para a stdout:

$ printf 'a
$ printf 'a
$ printf 'a
$ cmd=(printf 'a
$ "${cmd[@]}"| sed -n l
a
$ printf '%s\n' "$(printf 'a
$ ksh -c 'echo $(printf "a
$ bash -c 'echo $(printf "a
$ zsh -c 'echo $(printf "a
FILE="$(mktemp)"
printf "a
$ printf 'a
$ printf 'a
$ printf 'a
$ cmd=(printf 'a
$ "${cmd[@]}"| sed -n l
a
$ printf '%s\n' "$(printf 'a
$ ksh -c 'echo $(printf "a
$ bash -c 'echo $(printf "a
$ zsh -c 'echo $(printf "a
FILE="$(mktemp)"
printf "a%pre%b\n" > "$FILE"
S=$(xxd -p "$FILE")
xxd -r -p <(printf '%s' "$S") | xxd -p
rm "$FILE"
b\n")|sed -n l' a b$
b\n")|sed -n l' ab$
b\n")|sed -n l' # also yash a$
b')" | cat -A bash: warning: command substitution: ignored null byte in input ab$
0b$
b\n') $ echo "${cmd[@]}" printf a%pre%b\n $ eval echo "${cmd[@]}" printf a0bn
b' >outfile
b' | cat -A a^@b
b' | sed -n l a%pre%0b$
b\n" > "$FILE" S=$(xxd -p "$FILE") xxd -r -p <(printf '%s' "$S") | xxd -p rm "$FILE"
b\n")|sed -n l' a b$
b\n")|sed -n l' ab$
b\n")|sed -n l' # also yash a$
b')" | cat -A bash: warning: command substitution: ignored null byte in input ab$
0b$
b\n') $ echo "${cmd[@]}" printf a%pre%b\n $ eval echo "${cmd[@]}" printf a0bn
b' >outfile
b' | cat -A a^@b
b' | sed -n l a%pre%0b$

Ou:

%pre%

E para um arquivo também:

%pre%

E exatamente que também funciona em scripts.

eval

O problema com o seu primeiro script é que ele está usando eval :

%pre%

No segundo loop tru, as barras invertidas de análise da linha do shell foram removidas.
Apenas não use eval:

%pre%

expansões

Isso prova que ambos (o interno) printf e stdout são capazes de usar NULs.

Mas isso falha:

%pre%

Existe até (no bash 4.4+) uma mensagem de aviso.

Em resumo, o shell (a maioria dos shells) usa strings C internamente, uma string C termina no primeiro NUL. Algumas conchas cortadas na primeira NUL em uma "expansão de comando".

%pre%

Alguns removem o NUL

%pre%

E alguns até mudam o NUL para um espaço:

%pre%

Problemas semelhantes acontecem com atribuições a variáveis.

codificar

Sim, a resposta que você vincula para usar uuencode para codificar (e decodificar) o conteúdo do arquivo.

Uma abordagem mais simples parece ser usar xxd (que pode reverter dumps octal):

%pre%     
por 21.11.2018 / 01:18