短縮版
以下のコードでは、$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 セクションに誘導されます。そこには次のように書かれています。
use locale が有効な場合、Perl は汚染メカニズム (perlsec を参照) を使用して、文字列の結果がロケールに依存するようになり、結果的に信頼できない可能性があることをマークします。ロケールによって影響を受ける可能性のある演算子と関数の汚染動作の概要を次に示します。
比較演算子 (
lt
、le
、ge
、gt
およびcmp
) […]ケースマッピング補間 (
\l
、\L
、\u
または\U
) […]一致演算子 (
m//
):スカラーの true/false の結果が汚染されることはありません。
use locale
$1
( but notuse locale ':not_characters'
) が有効で、サブパターンの正規表現に\w
(英数字と一致するため)、\W
(英数字以外の文字)、\s
(空白文字)、または\S
(非空白文字)。use locale が有効で、正規表現に、、、またはが含まれている場合、matched-pattern 変数 、$&
($`
一致前)、$'
(一致後)、および$+
(最後の一致) も汚染されます 。\w
\W
\s
\S
置換演算子 (
s///
) […][⋮]
これは完全なリストであるように見えます。そして、それがどのように適用されるかわかりません。私の正規表現は\w
、\W
、\s
または\S
を使用していないため、ロケールに依存するべきではありません。
このコードが varibale を汚染する理由を誰かが説明できますか$1
?