我应该在Perl中转义shell参数吗?

Jay*_*Jay 14 shell perl arguments

在Perl中使用system()调用时,是否必须转义shell args,还是自动完成?

参数将是用户输入,因此我想确保这不可利用.

run*_*rig 37

如果您使用system $cmd, @args而不是system "$cmd @args"(数组而不是字符串),那么您不必转义参数,因为没有调用shell(请参阅系统). system {$cmd} $cmd, @args即使$ cmd包含元字符并且@args为空(这也记录为exec的一部分),也不会调用shell .如果args来自用户输入(或其他不受信任的来源),您仍然需要解开它们.见-Tperlrun文档和perlsec文档.

如果需要读取输出或向命令发送输入,qx并且readpipe没有等效项.相反,使用open my $output, "-|", $cmd, @argsopen my $input, "|-", $cmd, @args虽然这是不可移植的,因为它需要一个真正的fork,这意味着只有...我想.也许它可以在Windows上使用它的模拟分支.一个更好的选择就像IPC :: Run,它也可以处理管道命令到其他命令的情况,系统的多arg形式和open的4 arg形式都不会处理.

  • 我从来没有注意到他们添加了那种语法的+1.可爱. (3认同)

j_r*_*ker 13

在Windows上,情况有点糟糕.基本上,所有的Win32程序收到一个长命令行字符串-壳(通常cmd.exe)可以首先做一些解释,消除<>例如重定向,但它并没有在该程序字边界分裂它.每个程序都必须自己进行解析(如果他们愿意 - 有些程序不会打扰).在C和C++程序中,由编译器工具链提供的运行时库提供的例程通常在main()调用之前执行此解析步骤.

问题是,通常,您不知道给定程序将如何解析其命令行.许多程序都是使用某些版本的MSVC++编译的,其中描述了古怪的解析规则,但许多其他程序使用不同的编译器编译,这些编译器使用不同的约定.

cmd.exe具有其自身古怪的解析规则的事实加剧了这一点.caret(^)被视为引用以下字符的转义字符,如果满足棘手条件列表,则双引号内的文本将被视为引用(cmd /?有关完整的详细信息,请参阅参考资料).如果你的命令包含任何奇怪的字符,那么很容易cmd.exe知道哪些部分的文字被"引用",哪些不会与你的目标程序不同步,而且所有的地狱都会破裂.

因此,在Windows上转义参数的最安全方法是:

  1. 以您正在调用的程序的命令行解析逻辑所期望的方式转义参数.(希望你知道那个逻辑是什么;如果没有,试试几个例子并猜测.)
  2. 使用空格加入转义参数.
  3. 使用生成字符串的每个非字母数字字符前缀^.
  4. 附加任何重定向或其他shell欺骗(例如,加入命令&&).
  5. 使用system()或反引号运行命令.