我正在编写一个Perl脚本,用户可以在其中输入正则表达式和替换字符串.该脚本将搜索一组文件,并根据s///应用用户输入的perl 运算符应用更改.
为了使问题稍微复杂化,允许替换字符串包含反向引用以引用正则表达式中的捕获组.例如,如果正则表达式b(.*?)a和替换字符串是a$1b不$1应该按字面意思处理,但rater作为反向捕获第一组.
在这个设置中,我想知道当ee用户输入该s///操作符的右侧时是否可以安全地使用修饰符(以评估用户输入中的反向引用)?例如:
use strict;
use warnings;
my $str = 'abaaca';
my $replacement = 'do{ use Env qw(HOME); unlink "$HOME/important.txt" }';
$str =~ s/a(.*?)a/$replacement/gee;
Run Code Online (Sandbox Code Playgroud)
将是不幸的..但后来我有想法引用用户输入(把它放在一对双引号内)后转义双引号和美元符号(后面没有数字),然后做替换:
use feature qw(say);
use strict;
use warnings;
my $str = 'abaaca';
my $replacement = shift;
$replacement =~ s/\"/\\\"/g;
$replacement =~ s/\$(?!\d)/\\\$/g;
$replacement = '"' . $replacement . '"';
$str =~ s/a(.*?)a/$replacement/gee;
say $str;
Run Code Online (Sandbox Code Playgroud)
对我来说,这似乎乍一看,或者我错过了什么?例如,如果调用脚本test.pl并且用户将其运行为:
$ test.pl 'do{ "a$b" }'
Run Code Online (Sandbox Code Playgroud)
输出只需要一个简单的字符串(并且不评估代码):
做{"a $ b"}做{"a $ b"}
所以问题是:这真的是一种安全/正确的方法吗?
问题1:
有没有办法来取代$1其次1,因为下面有取代${1}1.
$ script '${1}1'
${1}1${1}1
Run Code Online (Sandbox Code Playgroud)
问题2:
$ script '\${ system "echo rm -rf /" }'
rm -rf /
Use of uninitialized value in substitution iterator at a.pl line 12.
rm -rf /
Use of uninitialized value in substitution iterator at a.pl line 12.
Run Code Online (Sandbox Code Playgroud)
问题3:
$ script '$1{ system "echo rm -rf /" }'
rm -rf /
Use of uninitialized value within %1 in string at (eval 1) line 1.
rm -rf /
Use of uninitialized value within %1 in string at (eval 2) line 1.
Run Code Online (Sandbox Code Playgroud)
当然,还有其他人.解: