PHP5.2.xとそれより前のバージョンで正規表現関数の動作が異なる

  • みんなで使う開発環境と、自分でちょっと試すための環境を別のサーバに持つケースがある。
  • そのときに、PHPやDBMSのバージョン、その他のモジュールすべてが完全に同じでないためにハマった。
  • 共通環境はPHP5.1.6。マイサーバはPHP5.2.x。テンプレートエンジンにSmarty。
  • ある日、マイサーバでアプリを動かすと、ログインフォームが動かない。そのプロジェクトでは、共通で使うJavascriptを共通テンプレートにして、各フォームでincludeしていた((リンクにしたほうが、キャシュが効いていいとは思うが))のだが、その部分が抜け落ちている。カーソル移動などをJSに頼っていたため、まったく動作しなくなってしまった。

調査

  • ソース、テンプレート、Smartyのソース、フレームワーク(ethnaベース)どれも同じ。
  • PHPのコンパイルオプションは違うが、どっから比べたらよいのか・・・しょうがないので、コードを追いかけ、やっとSmartyのコンパイル部分でテンプレートがカラッポになっていることが分かった。
  • しかし、カラッポになる理由がわからない。ダメな文字でも含まれているのかと、対象のテンプレートソース量を適当に半分くらいにすると、正常に読み込まれる。多くするとカラッポ。どうやらソースの長さによって挙動が変わるらしい。
  • ここでやっとgoogle検索してみると、たくさんの先人がいらっしゃいました。php5.2.0から、pcre.backtrack_limit、pcre.recursion_limitという設定オプションが増えたらしく、pcreの動作に影響するようだ。
  • デフォルトはどちらも100000 という値が設定されている。どういう単位なのか分からないが、とりあえず大きい値を設定してみると、動いた。ちなみに入力ファイルは119KB(119210Bytes)だった。
    • (実際はSmartyのキャッシュが残っていてもうちょっとハマッた)
  • php.iniを編集
[Pcre]
pcre.backtrack_limit=300000
pcre.recursion_limit=300000
  • .htaccessを編集してもOK
php_value pcre.backtrack_limit 300000
php_value pcre.recursion_limit 300000
  • 2日に渡って余計なことで時間を費やしてしまった。でも、警告もなしに、結果を空で返すってちょっといじわるだなあ。

facebook slideshare rubygems github qiita