関数の中にはバイナリデータを正しく扱うことが出来る関数(バイナリセーフ)とそうではない関数があります。これを把握しておかないと、思わぬところでバグを発生させかねません。今回はその中でも正規表現によるマッチングに焦点を当てます。

正規表現によるマッチング関数にpreg_matchとeregがあります。前者はPerl互換 性、後者はPHPのPOSIX互換性正規表現関数です。これらは入力値をフィルターす るときにしばしば用いられます。しかし、eregには落とし穴が存在します。

その落とし穴とは「ereg関数はバイナリセーフではない」ということです。例え ば、ユーザ入力をフィルタリングするスクリプトを考えてみましょう。

if (ereg('^[0-9A-Za-z_]+$', $_POST['login_id'])) {
// 正しい入力に対する処理
}

ここでの目的はポストされたlogin_idが半角英数、アンダーバーのみで構成され ているか確認することです。一見、何の問題もないように思われます。しかし、 $_POST['login_id']にヌルバイト文字(\0)を入れられると、このフィルタリン グは意味を持たなくなります。ためしに

$_POST['login_id'] = "abc\0 -** 1 **-";

としてみて下さい。ereg関数はtrueを返し、if内部のスクリプトが実行されたと 思います。この原因はereg関数がヌルバイト文字の直前までしかマッチングを行 わないことにあります。つまり、バイナリセーフな関数ではないため、ヌルバイ ト文字で文字列が終了したとみなしてしまいます。このような場合にはeregでは なくpreg_matchを用いて下さい。

ただし、これはmb_ereg系には当てはまりません。名前は似てい ますが、これらはバイナリセーフな関数です。また、preg系の関数ではその代 わりになりえません。

以上の様に、入力値に対してバイナリセーフではない関数を用いる場合には注意 が必要です。特に正規表現関数の使い所には気を付けて下さい。

他のバイナリセーフではない関数の一部

ereg_replace(), eregi(), eregi_replace(),
split(), spliti(),
include(), include_once(), require(), require_once()
fopen(), file_get_contents(), readfile(), basename()