💬

今週の PHP 2022/12/10 〜 2022/12/16

2023/01/09に公開

PHP のメーリングリストから、気になった情報をピックアップします。

Internal

Revisiting RFC: Engine Warnings -- Undefined array index - Externals

https://externals.io/message/119109

PHP 8.0 の互換性のない変更リストにも書いてありますが、未定義の配列キーを読み取ろうとした場合に、警告 E_WARNING になります。
7.4 までは、E_NOTICE だったものです。

https://www.php.net/manual/ja/migration80.incompatible.php

上記変更に関わる RFC はこちら -> https://wiki.php.net/rfc/engine_warnings

このおかげで、$arr['key'] という記述は isset($arr) && isset($arr['key']) && $arr['key'] という風に長ったらしく書かなければいけなくなってしまった。

20年も E_NOTICE にしてたのにひどいよ。なので、未定義の配列キーに対するエラーレベルを設定可能にしてくれないか?というご意見

これに対しては

  • 20年はそうだったかもしれないけど、直近3年は違うよ。
  • 移行期間は 2+1 年用意されていた。
  • E_WARNING になるだけで、振る舞いには変更がない。
  • この変更が覆ることはまず考えられない。

という、非常にもっともな意見が返されました。

PHP は、開発者が正しく開発できるようにする方向に向かっているから、この変化に追随しようよ。という意見や、実際に Undefined Index の状態と、それ以外に対するベンチマークを取ってくれた人もいました。

https://gist.github.com/withinboredom/bd7276b7703663c26c12a18820747bcb

言語的にも、Undefined Index が存在しないほうが、高速に動作します。Null 合体演算子の利用でも同様に高速動作しています。

すこし面白かったのは、Ubuntu 20.04 などで、パッケージ版の PHP を利用している方にとっては、PHP 7.4 はかなり身近な存在で、8.0 系にようやく乗り換えようというタイミングが今になっているという話でした。

手元の Ubuntu 22.04 LTS (Jammy) で確認しましたが、入れようと思えば、まだ PHP 7.4 を入れられそうでした。本当に 8.0 系大移動はこれからなのかもしれないですね。

話は、結構膨らんで

  • undefined っていう新しい primitive を返すようにしよう
  • Null 合体演算子は名前がおかしい

などなど、関係ない方向にも飛び火していきました。

Remove PHP-x.y.* git branches - Externals

https://externals.io/message/119135

下記のイシュー主からのお便り

Remove PHP-x.y.* git branches · Issue #10007 · php/php-src

要するに、一般的でなかったり、古かったりするブランチは削除しませんか?という話です。

具体的には

a) PHP-x-y-* のブランチ

internal のメール文面は多分あやまりで PHP-x.y.* と思われます。

例えばこれ -> https://github.com/php/php-src/tree/PHP-7.1.0RC3
過去を遡ると、かなり前のバージョンまで全部入っています。

b) 10年以上前のブランチ

めちゃくちゃ古いやつで、反映されてない変更はローカロのSVNから復帰させて、新しいプッシュすればいいよね?
そんなものがあればの話だが... という雰囲気

これに対する意見としては

  • リリースプロセスと結びついているので、修正するならリリースプロセスも直さないとだめ
  • Tag でバージョンは表現されているから、ブランチが不要なのはわかるけど、別に消さなくてもいいんじゃ?
  • バージョンをGUIのセレクターで選ぶときに、バージョンが多すぎて辛い
  • 確かに semver には沿ってないけど、コミュニティにいる人はすぐに慣れるのでは
  • PHP のリリースプロセスにおいて、分かりやすい名前の バージョンブランチがいることは良いと思う

などなど、消してもいいとは思うが、既存でも十分に回っているという感じの意見が多かったです。
リリースプロセスにも関わる話なので、RFC を整えるだけでも結構大変そうですね。

Bugs

Fix bug #79836: Segfault in concat_function by nielsdos · Pull Request #10049 · php/php-src

https://github.com/php/php-src/pull/10049

下記のようなコードで、SegV が出るというイシュー。現在も修正中ですが、原因はメモリーリークだったようです。

ob_start ( function () use ( & $c ) { $c = 0 ;}, 1 );
$c .= [];
$c .= [];

FTBFS PHP 8.2 on Ubuntu 18.04 ppc64el · Issue #10077 · php/php-src

https://github.com/php/php-src/issues/10077

ppc64el ってなにかなと思ったら、Little-Endian でした。

ppc64el - Ubuntu Wiki

こちらが修正パッチ

https://github.com/Cyan4973/xxHash/commit/15ce80f9f2760609d8cc68cea76d3f3217ab70e1

すでに解決済みです。

main/php_ini.c: remove dead code by glensc · Pull Request #4512 · php/php-src

https://github.com/php/php-src/pull/4512

Merge されるまでに3年4ヶ月かかったそうです。php_ini 関連の重複コード改善。

PHP 8.0+ does no longer accept a comment in the whitespace between ampersand and argument in function signature · Issue #10083 · php/php-src

https://github.com/php/php-src/issues/10083

引数内の & と 引数の間にコメントが書けなくなっているというイシュー

https://3v4l.org/aq2rT

実際に試してみると、8.1 系からはコンパイルに失敗します。これは、交差型の導入によりパースに変更が入ったためということです。

https://github.com/php/php-src/commit/069a9fa5e4478c7044cb6432258cfe207d10a202

というわけで won't fix のタグが入ったのですが、Lexer の正規表現を工夫したらイケるかもということで re-open されています。

https://github.com/php/php-src/pull/10125

& の後方にあるホワイトスペースとコメントを認識するという形に変更されています。
これが取り入れられると、コメントがまた書けるようになります。

もとのコードを見てみると、現状でも改行、タブは大丈夫なのですね。

https://3v4l.org/STghA

Add MariaDB to the Github actions by grooverdan · Pull Request #10062 · php/php-src

https://github.com/php/php-src/pull/10062

MariaDB (最新、安定版、ナイトリー) のテストを Github Actions に加えようよ!というイシュー。
これ意味あるの?とか、最新版だけで良くない?みたいな話がされています。

MariaDB が本番でそのまま使われるかは別として、世間の流れ的には抑えておくと良さそうなテストではありますね。
まだ、Draft なので、どうなるかは分かりません。

Assertion (zend_gc_refcount(&(ht)->gc) == 1) || ((ht)->u.flags & (1<<6))' failed. · Issue #10085 · php/php-src

https://github.com/php/php-src/issues/10085

PHP 8.3 の不具合報告。

不具合が混入したと推定されるコミットたち

https://github.com/php/php-src/commit/b96b88b669370e1d85b6e98e359649d73b548029
https://github.com/php/php-src/commit/edc7c8ccfa0eb7c6064575e2155f30797adf6684

配列周りの取り扱いで、入ったように思える。

コミッターの人が、「病的なコードなので、直るのかなんなのかよくわからん」と言っていて面白い。
もちろん、私にはわからんぞ。

Add CLEAN section to some IO tests by Girgias · Pull Request #10081 · php/php-src

https://github.com/php/php-src/pull/10081

--CLEAN-- というセクションを設けて、IO系のテストでの Fixture の処理が追加されたようです。

Anyone can lock a discussion for everyone else by getting "too heated" · Issue #10088 · php/php-src

https://github.com/php/php-src/issues/10088

too heated と言われてイシューがロックされてしまった!というイシュー。

ロックされたイシューがこちら

https://github.com/php/php-src/issues/8906

Internal 側でも、熱く盛り上がっていました。

議論の場は、Internal Mailing List であって、Github Issues じゃないよということで、ひとまず落着

Change status of BCMath into Maintained by frederikbosch · Pull Request #10089 · php/php-src

https://github.com/php/php-src/pull/10089/files

BCMath はちゃんとメンテナンスされてるよね。というわけで、 Unknown から Maintained に変更。

Internal stream casting should not emit lost bytes warning twice · Issue #10092 · php/php-src

https://github.com/php/php-src/issues/10092

<?php
$handle = fopen('http://example.com', 'r');
var_dump(stream_isatty($handle));

このコードを実行すると、同じWarning が2回出てしまうというイシュー

修正内容を見ると、エラーをすでに送出したことをチェックしていなかったことが原因

https://github.com/php/php-src/pull/10093/files

Regex doesn't returns expected result · Issue #10096 · php/php-src

https://github.com/php/php-src/issues/10096

正規表現が意図する動作をしないというイシュー

複雑な正規表現で、Back Track が大量に発生していたのが原因だったので、クローズされました。
正規表現で無理やりなパースを行う事例は結構あると思うのですが、 pcre.backtrack_limit という設定を超えては Back Track してくれませんのでご注意。

こういうケースでは、正規表現を特定の用途に絞るか、対象の文章を少なくするなどの工夫が必要かと思います。

コメントでは、U フラグを指定して、「欲張り」しないようにしてあげたら?などのアドバイスもありました。

curl_setopt(_array) should warn on errors · Issue #10097 · php/php-src

https://github.com/php/php-src/issues/10097

もともとは、curl で特定のオプションの設定が反映されないというイシューでしたが、curl_setopt 及び curl_setopt_array がエラー発生時に Error にしないというタイトルに変更になりました。

サイレントエラーは、実に見つけにくいですね。

realpath() with empty path should return false · Issue #10101 · php/php-src

https://github.com/php/php-src/issues/10101

file_exists is_dir の場合、空文字の入力が渡されると、false が返ってくるのに realpath ではカレントディレクトリが返ってくる。これは一貫性がないのでは?というイシュー

Null Coercion といい、空文字が渡されたときの戻り値といい、このあたりの一貫性問題は基本的に後方互換性を破壊してしまうので難しいところではありますね。

Add Randomizer::nextFloat() and Randomizer::getFloat() by TimWolla · Pull Request #9679 · php/php-src

https://github.com/php/php-src/pull/9679

PHP: rfc:randomizer_additions

RFC が受理されたため、実装が master にマージされました。というわけで、お試ししたい人は新しいメソッドを利用することが可能です。

json_decode() fails on nested input of around 10000 characters. · Issue #10104 · php/php-src

https://github.com/php/php-src/issues/10104

深くネストした JSON で json_decode が失敗するというイシュー

ネストした JSON の例

[[[[[[[[[[1]]]]]]]]]]

ext/json の Makefile を見ると、下記のコードで parser が出力されています。

$(BISON) --defines -l ext/json/json_parser.y -o ext/json/json_parser.tab.c

json_parser.tab.c では YYMAXDEPTH = 10000 となっているため、これが nest 10000 が上限となっている理由です。

そもそも、そんなにネストした JSON って... という気持ちになりますが、自前でコンパイルすれば、変更することはできそうですね。

php_admin_[flag|value] falsely applies config changes · Issue #10117 · php/php-src

https://github.com/php/php-src/issues/10117

php_admin_flag の設定によって、誤って ini の設定が上書きされるという不具合。
Opcache による設定キャッシュが主原因と見られるので、下記イシューが要チェックです。

Wrong value from ini_get() for shared files because of opcache optimization · Issue #8699 · php/php-src

本番で、新しめの PHP を使っている場合は、注意する必要がありそうです。

PHP :: Bug #81743 :: XSS via PDOException error

https://bugs.php.net/bug.php?id=81743&edit=1

HTML_ERRORS の設定にもよりますが、PDO の例外経由で XSS を発生させられるというイシュー。先週も取り扱ったような気がする...。

Discussion