Perlの汚染モードに苦戦

Perlには「汚染モード」というのがあって、-Tオプションを使用すると有効になります。こんな感じで。

#!/usr/bin/perl -wT

汚染モードの目的はPerlに対してユーザーからのデータを追跡し、そのデータを使った危険な処理を実行しないように指示することです。
CGIプログラミングによれば、

汚染モードが有効になると、Perlはすべての変数を監視して汚染されているかどうかをチェックします。Perlは、コードの外から来たすべてのデータは汚染されていると判断します。これには、環境変数はもちろん、STDIN(またはその他の入力ファイル)から読み込まれたすべてのデータも含まれるので、CGIスクリプトがユーザから受け取るすべてのデータをカバーします。

とのことであり、

CGIスクリプトでは常に汚染モードを使うべきです。

とも言っています。一方で、慣れないとイライラするかもね、とも言っています。とりあえずこれまで何も言わずに使っていたし、これに起因する問題も特に発生していなかったのですが今日始めて遭遇しました。これはその記録です。
以下が問題のコードです。BBS::MessageはClass::DBIのサブクラス。$min_idの定義は省略。

my $max_id = BBS::Message->maximum_value_of('id')
my @messages = BBS::Message->retrieve_from_sql(qq!
        id > $min_id AND
        id <= $max_id
        ORDER BY id DESC
!);

IDが$min_idから$max_idのメッセージを降順に取得します。
でもなぜかエラー。以下のメッセージ。

Error executing run mode 'rss': Insecure dependency in parameter 1 of DBIx::ContextualFetch::db=HASH(0x
86b5c50)->prepare_cached method call while running with -T switch at /usr/local/share/perl/5.8.4/Ima/DB
I.pm line 391.
at /usr/local/share/perl/5.8.4/CGI/Application/Dispatch.pm line 340

困惑。
どうやら$max_idに直接数字を代入してretrieveすると問題は発生しないようだということがわかる。じゃあ$max_idには何が入っているのかと、値を直接表示してみるとちゃんと正しい値が表示される。
ん??
エラーメッセージを見つめてみると「while running with -T switch」という文字が見つかる。なるほど!汚染モードか。$max_idは汚染されているのか!と気づく。
ここまでで1時間くらいかかる。
CGIアプリケーション」によると

変数を正規表現にマッチさせると、マッチした括弧に一致するパターンマッチ変数($1、$2など)からは汚染が除去されるのです。

とのことで、以下のようにして汚染を除去して問題解決しました。

my ($max_id) = BBS::Message->maximum_value_of('id') =~ /([\d]+)/; # remove taint
    • -

あと今日は以下の機能を実装。

  • 降順のページング処理
  • プレビュー
  • 返信
  • RSS(まだ途中)

楽しかったけど疲れた。