さらに強力な汚染チェック(テイントモード)
これまでのチェックでも一通りの問題を防げそうですが、Perlにはさらに、プログラマのうっかりミスを防ぐ強力なツールがあります。これを「テイントモード」と呼び、perl 実行時に「-T」というオプション(※3)を追加して実行すると有効になります。※3 Perlではこのような実行オプションを「スイッチ」と呼びます。
では、テイントモードで、動作がどう変化するか見てみましょう。
% perl -T prog.pl 笑う長さを指定して下さい(数字): 20 保存するファイル名を指定して下さい(半角英数字): taintcheck.txt わーっはっはははははははははは。わーっはっはははははははははは。 Insecure dependency in open while running with -T switch at prog.pl line 41, <STDIN> line 2.またエラーメッセージが表示されるようになってしまいました。また、指定した名前のファイル taintcheck.txt は作成されていない事も確認して下さい。
このエラーメッセージは、「外からの入力を、ファイル名指定に使ったら危険だよ。」という主旨の警告です。テイントモードでは、危険を感知すると自動的にその直前の行までで実行を停止します。
Perlの用語ではこのような危険な外部からの入力を「汚染されている」と表現します。「汚染」とは穏やかでない感じですが、例えばこういう事です。
先ほど追加した入力チェックでは、たまたまディレクトリの区切りを表すスラッシュは許可しませんでしたが、「present/result.txt」位はいいかな、と思ってスラッシュも許可していたら、「/path/to/important/file」などと指定され重要なファイルを上書きしてしまうかもしれません。
このようなうっかりミスをチェックするために、怪しいところは警告してくれるのがテイントモードなのです。ですからこのスイッチは開発中に使うものです。開発中に、警告が出た箇所は十分に検討した上で、問題がないと判断したら「汚染を除去」します。
テイントモードの汚染除去方法
今回はファイル名としてスラッシュを許可しませんでしたので、このままで大丈夫そうですので「汚染除去」を行いましょう。テイントモードで警告された場所を「十分に検討して確認しましたのでもう警告しないで下さい」とPerlに伝えます。これには正規表現を使います。汚染除去のための変更(太字部分)
print '保存するファイル名を指定して下さい(半角英数字): '; my $outfile_input = <STDIN>; chomp $outfile_input; if ($outfile_input =~ m/^([a-zA-Z0-9._-]+)$/){ $outfile = $1; } else { die "ファイル名の指定が違います。\n"; }先ほどは正規表現でファイル名のチェックをしただけでしたが、汚染の「除去」は、正規表現でマッチした部分を取り出してファイル名に代入します。そうすると、Perlは「この変数は形式が安全だと確認された」と認識し、警告を出すのを止めてくれます。
上のサンプルコードでは、正規表現でマッチした部分を取り出しているのが「$1」の部分です。これはPerlの特殊変数(※4)で、直前の正規表現でマッチした文字列のうち、カッコでくくられている部分が格納されています。ここでは、ファイル名チェックの正規表現全体をカッコでくくっているので、ファイル名全体が $1 に代入されています。
※4 特殊変数とは
特殊変数は、Perlの中で予め定義されて自動的に状況に応じた値が格納されている変数の事です。
プログラムを変更したらもう一度実行して下さい。今度はファイルも保存されている筈です。
>次は: ポイント3 サブルーチンの引数をチェック