【发布时间】:2013-12-06 09:20:29
【问题描述】:
短版
在下面的代码中,$1 被污染了,我不明白为什么。
加长版
我在启用了-T 污点检查模式的 perl v5.14.2 系统上运行 Foswiki。
调试该设置的问题后,我设法构建了以下 SSCCE。 (注意我编辑了这个帖子,第一个版本更长更复杂,cmets仍然参考。)
#!/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 假定如果 您使用
$1、$2等引用子字符串,您知道自己在做什么 你写模式时正在做的事情。
我想即使输入被污染,输出仍然是未污染的。从未污染的输入观察相反的污染输出,感觉就像 perl 中的一个奇怪的错误。但是,如果阅读更多 perlsec,它也会将用户指向the SECURITY section of perllocale。我们读到:
当使用区域设置生效时,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?
【问题讨论】:
-
我认为如果你删除(奇怪的写作方式)
use locale;,它不会被污染?使用perlbug工具将其发送到p5p不会有什么坏处。如果不是文档中的错误,Perl 中似乎存在错误。 -
Scalar::Util qw(tainted)有什么问题? -
@mpapec:
Scalar::Util::tainted没有问题,它产生相同的结果。我只是在此处粘贴了 Foswiki 使用的代码,因为它可能会稍微减少该代码的依赖关系。我不知道是否每个人都有可用的Scalar::Util,文档建议使用 CPAN。 -
Scalar::Util 自 5.8.0 以来一直是核心模块,十多年前。
-
@ikegami:报告于rt.perl.org/Public/Bug/Display.html?id=120675