精简版
在下面的代码中,$1
被污染了,我不明白为什么。
长版
我在启用了污点检查模式的 perl v5.14.2 系统上运行Foswiki 。-T
调试该设置的问题后,我设法构建了以下 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 手册对污点和正则表达式有这样的说法:
通过将它们用作散列中的键,值可能不会受到污染;否则绕过污染机制的唯一方法是从正则表达式匹配中引用子模式。Perl 假定如果您使用
$1
,$2
等引用子字符串,那么您在编写模式时就知道自己在做什么。
我想即使输入被污染,输出仍然是未污染的。从未污染的输入观察相反的污染输出,感觉就像 perl 中的一个奇怪的错误。但是,如果阅读更多 perlsec,它也会将用户指向perllocale 的 SECURITY 部分。我们在那里读到:
当使用区域设置生效时,Perl 使用污染机制(参见 perlsec)来标记字符串结果,这些结果变得依赖于区域设置,因此可能是不可信的。以下是可能受语言环境影响的运算符和函数的污染行为的摘要:
比较运算符(、、、和
lt
)[ … ]le
ge
gt
cmp
案例映射插值(使用、 或
\l
)\L
[ …]\u
\U
匹配运算符 (
m//
):标量真/假结果永远不会被污染。
$1
如果使用区域设置(但不是)有效,并且子模式正则use locale ':not_characters'
表达式包含\w
(以匹配字母数字字符)、\W
(非字母数字字符)、\s
(空白字符)或\S
(非空白字符)。如果使用区域设置有效并且正则表达式包含、、或,则匹配模式变量 、$&
($`
匹配前)、$'
(匹配后)和$+
(最后匹配)也会受到污染 。\w
\W
\s
\S
替换运算符 (
s///
) […][⋮]
这看起来应该是一个详尽的列表。而且我看不出它如何应用:我的正则表达式没有使用 , 或 中的任何一个\w
,所以\W
它不应该依赖于语言环境。\s
\S
有人可以解释为什么这段代码会污染变量$1
吗?