我想评估一个环境变量并将结果设置为一个变量:
$x=eval($ENV{EDITOR}); print $x;
输出:
/bin/vi
工作良好.
如果我将环境变量QUOTE设置为\'并尝试相同的事情:
$x=eval($ENV{QUOTE}); print $x;
输出:
(没有)
$@ set to: "Can't find a string terminator anywhere before ..."
我不希望简单地设置$x=$ENV{QUOTE};
为eval也用于调用脚本并返回其最后一个值(非常方便),所以我想坚持使用eval(); 请注意,以这种方式评估的所有环境变量都是由我在不同的地方设置的,所以我不关心以这种方式恶意访问环境变量eval-ed.
建议?
嗯,当然它什么都不做.
如果您的ENV变量包含的文本是半码,但不是,并且您将结果字符串提供给将该代码评估为Perl的内容,当然它不会起作用.
您只有3个选项:
以编程方式处理字符串,使其中没有无效语法
手动确保您的ENV变量不是垃圾
找到一个不涉及eval的解决方案,但会给出正确的结果.
你也可以抱怨
$x = '
不是有效的代码,因为这基本上是正在发生的.
# Bad. QUOTE="'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"' # Can't find string terminator "'" anywhere before EOF at (eval 1) line 1. # Bad. QUOTE="\'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"' # Can't find string terminator "'" anywhere before EOF at (eval 1) line 1. # Bad. QUOTE="\\'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"' # Can't find string terminator "'" anywhere before EOF at (eval 1) line 1. # Good QUOTE="'\''" perl -wWe 'print eval $ENV{QUOTE}; print "$@"' # '
你为什么要eval
放在第一位?你应该说吗?
my $x = $ENV{QUOTE}; print "$x\n";
在eval
正在执行中的字符串$ENV{QUOTE}
就好像它是Perl代码,我当然希望这不是.这就是\消失的原因.如果你要检查$@
变量,你会发现一条错误消息
在EOF处的(eval 1)第2行的语法错误
如果环境变量将包含Perl应该执行的代码,那么您应该查看安全模块.它允许您控制可以执行的代码类型,eval
这样您就不会意外地执行类似的操作"use File::Find; find sub{unlink $File::Find::file}, '.'"
评估环境值非常危险,如果在污染模式下运行会产生错误.
# purposely broken QUOTE='`rm system`'
$x=eval($ENV{QUOTE}); print $x;
现在想象一下,如果此脚本是以root访问权限运行的,并且已更改为实际删除文件系统.