42
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

preg_matchが2を返す

Last updated at Posted at 2019-11-25

https://bugs.php.net/bug.php?id=78853

preg_matchは、パターンにマッチした場合は1を、マッチしなければ0を、エラーが発生したらfalseを返します。

01.png

ということでこんな正規表現を試してみましょう。

var_dump(preg_match('/^|\d{1,2}$/', "7"));

結果

02.png

なんだこれ?

2が返ってきました。
仕様が変わったけどドキュメントが更新されてなくて古いのかと思えば英語版にもしっかり"1か0かfalseを返す"と書いてあって、ドキュメントが古いわけでもなさそうです。

PHP7.3から発生するようになったみたいなので、ちょっくら原因でも探ってみるかとソースを覗いてみたのですが、
7.3.0
7.2.24

諦めました。

ちなみにPHP7.0でコンパイルオプションpcre.jitというものが追加され、正規表現にJITを使うようになっています。
このJIT用メモリというのが意外と小さく、たとえば以下の正規表現はpcre.jitの状態によって返り値が変わってきます。

var_dump(preg_match('/^(A{1,2}B)+$/',str_repeat('AB',8192)));

pcre.jit=0であれば返り値は正しく1となります。
しかし、デフォルトのpcre.jit=1であれば返り値はfalseとなり、preg_last_errorにはJIT用メモリが足りないよというPREG_JIT_STACKLIMIT_ERRORが返ってきます。

でもpcre.jit=0にしても、最初の正規表現では2が返ってきました。
preg_last_errorを確認してもエラーは起こっていないので、pcre.jitは特に関係ないようです。

さてこのバグですが、先日修正されました
7.4にもマージされたので、2019/11/28リリース予定のPHP7.4.0正式版ではなおっていると思います。

なお、中身はifをひとつ突っ込んだだけで、どうしてこんなので直るのかさっぱりわかりません。

42
15
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?