汚染モードの罠

Perlの汚染モードは安全なプログラムを書くための便利な道具なのですが、三項演算子の扱いにバグがあるみたいです*1

以下のプログラムは、汚染された変数 $arg を比較のために使っていますが、結果となる @res は汚染されていないはずです。

#!/usr/bin/perl -T

my $arg = shift @ARGV;

my @res = map { $_ eq $arg ? "$_+" : "$_-" } (0..9);
{ my $x = join('',@res), kill 0; }    # 汚染チェック

ところが、これを実行すると、以下のようにエラーとなります。

Insecure dependency in kill while running with -T switch at taint.pl line 6.

等価なif文に書き換えると文句を言われません。

#!/usr/bin/perl -T

my $arg = shift @ARGV;

my @res = map { if ($_ eq $arg){ "$_+" }else{ "$_-" } } (0..9);  # if文にした
{ my $x = join('',@res), kill 0; }    # 汚染チェック

if文にするのは冗長で気持ちが悪いので、以下のようにして逃げてます。実行効率は良くないですが。

#!/usr/bin/perl -T

sub clean { local $_ = shift; /(.*)/s; $1 }  # 汚染チェック回避

my $arg = shift @ARGV;

my @res = map { $_ eq clean($arg) ? "$_+" : "$_-" } (0..9);
{ my $x = join('',@res), kill 0; }    # 汚染チェック

*1:Perl 5.8.8の場合。以降のバージョンでは試してません。