Contra-exemplo:
DANGEROUS=">foo"
eval echo $DANGEROUS
Os argumentos arbitrários para echo
poderiam ter feito algo mais nefasto do que criar um arquivo chamado "foo".
O uso de eval
costuma ser desencorajado porque permite a execução de código arbitrário. No entanto, se usarmos eval echo
, então parece que o resto da string se tornará argumentos de echo
, então deve ser seguro. Estou certo sobre isso?
@Celada forneceu uma excelente resposta. Para demonstrar eval
é realmente mal, aqui está algo mais nefasto do que criar um arquivo chamado "foo" :
DANGEROUS='$(rm foo)'
eval echo "$DANGEROUS"
E é claro que pode haver algo mais nefasto do que algo mais nefasto do que criar um arquivo chamado "foo" .
Não, é não sempre seguro. Um eval poderia executar qualquer comando.
Um comando seguro, como este (a data não é executada como está entre aspas simples):
$ echo '$(date)'
$(date)
Torna-se perigoso se usado com eval:
$ eval echo '$(date)'
Sat Dec 24 22:55:55 UTC 2016
É claro que data pode ser qualquer comando .
Uma maneira de melhorar isso é citar adicionalmente os argumentos para eval:
$ eval echo '\$(date)'
$(date)
Mas geralmente é difícil citar corretamente duas vezes uma expressão.
E torna-se impossível controlar a citação correta se a expressão puder ser definida por um invasor externo, como:
$ var='$(date);echo Hello!'
$ eval echo "$var"
Sat Dec 24 23:01:48 UTC 2016
Hello!
Embora seja verdade que eval
sempre precisa ser abordado com cuidado, a construção eval echo
nem sempre é inútil e pode ser usada com segurança. Recentemente, precisei dele para obter várias expansões de chaves avaliadas na ordem que eu precisava delas.
bash
faz múltiplas expansões de chaves da esquerda para a direita, então
xargs -I_ cat _/{11..15}/{8..5}.jpg
expande para
xargs -I_ cat _/11/8.jpg _/11/7.jpg _/11/6.jpg _/11/5.jpg _/12/8.jpg _/12/7.jpg _/12/6.jpg _/12/5.jpg _/13/8.jpg _/13/7.jpg _/13/6.jpg _/13/5.jpg _/14/8.jpg _/14/7.jpg _/14/6.jpg _/14/5.jpg _/15/8.jpg _/15/7.jpg _/15/6.jpg _/15/5.jpg
mas eu precisava da segunda expansão de chave primeiro, produzindo
xargs -I_ cat _/11/8.jpg _/12/8.jpg _/13/8.jpg _/14/8.jpg _/15/8.jpg _/11/7.jpg _/12/7.jpg _/13/7.jpg _/14/7.jpg _/15/7.jpg _/11/6.jpg _/12/6.jpg _/13/6.jpg _/14/6.jpg _/15/6.jpg _/11/5.jpg _/12/5.jpg _/13/5.jpg _/14/5.jpg _/15/5.jpg
O melhor que eu pude fazer foi
xargs -I_ cat $(eval echo _/'{11..15}'/{8..5}.jpg)
Isso funciona porque as aspas simples protegem o primeiro conjunto de chaves da expansão durante a análise da linha de comando eval
, deixando-as para serem expandidas pelo subshell chamado por eval
.
Pode haver algum esquema astucioso envolvendo expansões de chaves aninhadas que permitem que isso aconteça em uma etapa, mas se houver, sou muito velho e estúpido para vê-lo. Há também outros shells que não bash
que permitem maneiras mais fáceis de alcançar esse tipo de coisa. Mas em qualquer caso, esse uso de eval
é seguro porque seus argumentos são todos sequências fixas que não contêm expansões de parâmetros.