二度忘れた事を三度忘れないようにする

しがないフリーランスIT系エンジニア

PHPのpreg_matchについて

いろいろなところで利用されているpreg_matchについてはまったのでメモ。
今回はまったのはcodeigniterのクエリビルダで使われているところで、
nginxのエラーログから調査していたけど、ちゃんとした内容がみつからなかった。

・エラー内容
Warning: preg_match(): Compilation failed: regular expression is too large at offset XXXXX

なにやら最後の数字(恐らくByte)を超えるとpreg_matchが意図した動作をしないようで。
日本語情報のほとんどが「pcre.backtrack_limit」と「pcre.recursion_limit」の上限を上げると解消する、というもの。backtrackというのがどういった動作に影響する値かが良くわからなかったけど、今回の現象とは違うと思いつつ設定したけど案の定解決せず。

おそらくpcreのコンパイルオプションで「link size」という値をデフォルトの2から3以上にすると解決するのではないかというところまで調べたけど時間切れで諦めた。
そもそもで正規表現にかけてる文字数が多すぎるのが、誰が見てもイケてないという結論になったのでそこを修正した。

ということで今回のハマリで注意することは、

フレームワークでは結構使われているので、他人事ではない。

・上記warningが出た場合、マッチするはずであろうがなかろうがreturnは「0」になる。

・warningなので処理が続行されてしまうので、条件分岐では「x==0」のようにしない。
 (マッチしない場合も0、warningが出た場合も0なので意図した条件分岐にならない可能性が高い)

・使用上どうしても長い・大きい値を正規表現にかけないといけない場合はpcreをコンパイルし直す。

・pcreなのでpreg_match以外のpcre系関数でも同様の制限がかかる模様。

・特に他人が書いたコードでは要注意。