Pergunta

Ao usar () chamadas em Perl, você tem que escapar do shell args, ou isso é feito automaticamente?

Os argumentos será a entrada do usuário, então eu quero ter certeza que isto não é explorável.

Foi útil?

Solução

Se você usar system $cmd, @args em vez de system "$cmd @args" (uma matriz em vez de uma string), então você não tem que escapar dos argumentos porque nenhum shell é invocado (veja sistema ). system {$cmd} $cmd, @args não vai invocar um shell quer mesmo se $ cmd contém metacaracteres e @args está vazia (isto é documentado como parte de exec ). Se os argumentos são provenientes de entrada do usuário (ou outra fonte não confiável), você ainda vai querer untaint eles. Veja -T no perlrun docs, e perlsec docs.

Se você precisa ler a entrada de saída ou enviar para o comando, qx e readpipe não têm equivalente. Em vez disso, o uso open my $output, "-|", $cmd, @args ou open my $input, "|-", $cmd, @args embora este não é portátil, pois requer uma fork real, o que significa Unix única ... Eu acho. Talvez ele vai trabalhar no Windows com seu garfo simulado. A melhor opção é algo como IPC :: Run , que também irá lidar com o caso de tubulação comandos para outros comandos, que nem a forma multi-arg do sistema nem a forma 4 arg de alça será aberta.

Outras dicas

No Windows, a situação é um pouco mais desagradável. Basicamente, todos os programas Win32 receber uma cadeia longa de linha de comando - o shell (geralmente cmd.exe) pode fazer alguma interpretação primeira, removendo < e > redirecionamentos por exemplo, mas ele faz não dividi-lo em palavra limites para o programa. Cada programa deve fazer isso analisar-se (se desejarem - alguns programas não se incomode). Em programas em C e C ++, rotinas fornecidas pelas bibliotecas de tempo de execução fornecidas com o toolchain compilador irá geralmente executar esta etapa de análise antes main() é chamado.

O problema é, em geral, você não sabe como um determinado programa irá analisar sua linha de comando . Muitos programas são compilados com alguma versão do MSVC ++, cuja peculiar de análise regras são descritas aqui , mas muitos outros são compilados com diferentes compiladores que usam diferentes convenções.

Esta situação é agravada pelo fato de que cmd.exe tem suas próprias regras peculiar de análise. O acento circunflexo (^) é tratado como um caractere de escape que cita o caráter seguinte, e de texto dentro de aspas duplas é tratado como citado se uma lista de critérios complicados são satisfeitas (ver cmd /? para os detalhes completos). Se o seu comando contém quaisquer caracteres estranhos, é muito fácil para a ideia de cmd.exe de que partes do texto são "citado" e que não estão a sair da sincronia com o seu programa de destino do e ele explodir.

Assim, a abordagem mais segura para escapar argumentos no Windows é:

  1. argumentos escape da maneira esperada pela linha de comando a análise lógica do programa que você está chamando. (Espero que você sabe o que a lógica é, se não, tente alguns exemplos e acho.)
  2. Junte-se aos argumentos escaparam com espaços.
  3. Prefixo cada personagem não alfanumérico da cadeia resultante com ^.
  4. acrescentar quaisquer redireccionamentos ou outros artifícios escudo (por exemplo, juntando os comandos com &&).
  5. Execute o comando com system() ou acentos graves.
 sub esc_chars {
  # will change, for example, a!!a to a\!\!a
     @_ =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g;
     return @_;
  }

http: //www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html

Se você usar o sistema "$ cmd @args" (a string), então você tem que escapar dos argumentos porque um shell é invocado.

Felizmente, para cadeias entre aspas duplas, apenas quatro personagens precisam escapar:

"    - double quote
$    - dollar
@    - at symbol
\    - backslash

As respostas sobre a sua pergunta foram muito úteis. No final, eu seguido de @ Runrig conselhos, mas, em seguida, usou o open3 módulo central () de comando para que eu pudesse capturar a saída de STDERR, bem como STDOUT.

Para código de exemplo de open3 () em uso com @ de Runrig solução, ver a minha pergunta e resposta relacionada:
Chamando comandos do sistema de Perl

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top