🌊

preg_match関数の文字数制約

2024/11/06に公開

先に結論を申し上げますと以下の通りです。

  • preg_match 関数で検索対象とする文字列の長さにはある程度制約がある模様
  • 具体的に何文字まで・何バイトまでという定義はない、というか文字列の構成で変わっている気もする

preg_match 関数とは、PHPで正規表現を行い、その結果を取得する関数。
詳しい事は公式のマニュアルをご覧いただくとして。

先日、Base64エンコードした文字列を受け取ってデコードし、ファイルとしてサーバに保存する処理を書いていたところ、どういうわけか一部のファイルだけデコードに失敗することがあり、調査していったところ判明しました。
何でBase64のデコードにpreg_match関数が関係あったのかは後で説明するとして、探していくとどうやら pcre.backtrack-limit という値が関係しているようでした。

PCRE 実行時設定

上記によると、この pcre.backtrack-limit の値が初期値は 1,000,000。
これが具体的にどのように preg_match 関数に関わってくるのかは分かりません。単純に文字数やバイト数ではないような気もしております。再帰処理の数とかその辺かなあ。
いずれにせよ、対策として考えられるのは以下の2通りです。

対策1:正規表現を掛ける箇所以外を捨てる

今回採用したのはこちらでした。
Base64エンコードされた文字列をデコードするにあたり、冒頭にMIME Typeを示す文字列があったらそれを取り除いて base64_decode 関数に掛けるということをしていたので、MIME Typeが出現するであろう冒頭100文字以内を preg_match 関数の対象にすることで、解決できました。

対策2:PHP設定を変える

対策1は、文中のどこにマッチする文言が出てくるか分からないケースでは採用できません。
では正規表現を掛ける文字列を何分割かにするかというと、その分割した境目にマッチさせたい文字列があった場合には検出できなくなります。

そういう場合には pcre.backtrack-limit 自体の定義を ini_set 関数を使って、もしくは php.ini.htaccess への追記で恒久的に変更して、解決できるかもしれません。
試していないので分かりません。

Discussion