精简版

在下面的代码中,$1被污染了,我不明白为什么。

长版

我在启用了-T污点检查模式的perl v5.14.2的系统上运行Foswiki
调试该设置的问题后,我设法构造了以下SSCCE。 (请注意,我编辑了这篇文章,第一个版本更长且更复杂,并且注释仍然涉及到该版本。)

#!/usr/bin/perl -T
use strict;
use warnings;
use locale;
use Scalar::Util qw(tainted);
my $var = "foo.bar_baz";
$var =~ m/^(.*)[._](.*?)$/;
print(tainted($1) ? "tainted\n" : "untainted\n");

尽管输入字符串$var未被污染并且正则表达式是固定的,但结果捕获组$1却被污染。我觉得真的很奇怪。

perlsec manual关于污点和正则表达式有这样的说法:



我可以想象,即使输入受到污染,输出仍然不会受到污染。要观察来自未污染输入的相反的,污染的输出,感觉就像是perl中的一个奇怪的错误。但是,如果人们读到更多的perlsec信息,它还会将用户指向the SECURITY section of perllocale。在那里,我们读到:



看起来应该是一个详尽的 list 。而且我不知道它如何应用:我的正则表达式未使用\w\W\s\S中的任何一个,因此它不应该依赖于语言环境。

有人可以解释为什么此代码污染了varitale $1吗?

最佳答案

从问题中引用的文档到Perl 5.18.1的实际实现之间当前存在差异。问题是字符类。该文档在听起来像是详尽无遗的列表中提到了\w\s\W\S,而该实现几乎污染了[…]的每一次使用。

正确的解决方案可能介于两者之间:[[:word:]]之类的字符类应受到污染,因为它取决于语言环境。我的固定 list 不应该。像[a-z]这样的字符范围取决于排序规则,因此我个人认为它们也应保持污点。 \d取决于语言环境对数字的理解,因此,即使到目前为止既不是上述转义序列之一,也不是方括号类,它也应该受到污染。

因此,我认为文档和实现都需要修复。 Perl开发人员正在为此进行工作。有关进度信息,请查看我提交的the perl bug report

对于固定的字符列表,一种可行的解决方法似乎是将其表示为一种分离形式,即(?:\.|_)而不是[._]。它比较冗长,但即使在当前(我认为是 buggy )的perl版本中也可以使用。

关于regex - 通过正则表达式进行Perl污染,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20355879/

10-11 20:17