🌴

今週の PHP 2022/08/20 〜 2022/08/26

2022/08/27に公開

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

Internal

Proposal for floored division and modulo functions

  • floor technique
  • truncation technique

という2つの考え方について、まず解説されています。

floor technique を使った div と mod を PHP に追加しようという

floor_div
floor_mod

RFC: json_validate

https://wiki.php.net/rfc/json_validate

is_json という名前で相談が来ていた件が、RFCとして提出されました。
名称は json_validate に変更になっています。

すでに実装も行われています。

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

事前の議論も活発に行われていて、懸念点やメモリ使用量の計測など、実用面での話し合いもなされていたので、これは通るんじゃないかなという気がします。

RFC にも議論の内容がフィードバックされて追加されています。今週目についたのは

so I would suggest to add that fast / efficient validation of a
common communication format reduces the attack surface for
Denial-of-Service attacks.

よく使われる通信フォーマットに対して、効果的なバリデーションを言語側が用意するのはセキュリティ的にも良いよねという視点

他にも、深さ制限を突破した際は、false 以外のなにか例外をスローなどしたほうが良いのでは?など、議論がマジで活発。

Nullsafe array access can still emit a warning - Externals

https://externals.io/message/118460

Nullsafe は、array access ではWarningでるんだけど、という相談

https://3v4l.org/1raa8

Nullsafe は Undefined Safe ではない。だから、このWarningは正しいという意見

もし、これで Warning を出したくないのであれば、Access Safe Operator が必要だねと

$arr[?0]

見た目がキモいですが、なるほどという感じです。
NullSafe operator は、利用箇所を is_null でラップしたような挙動になるので、やはり undefined は対象外という認識で良さそうです。

私もサンプルコードを書いてみました。
$a は正常、$b はNull $c は undefined です。

https://3v4l.org/vMEvT#v8.1.9

mb_trim の続報

RFC 出そうとしているひとが、メーリスに入れなくて止まっているという悲しい状態です。

What type of Exception to use for unserialize() failure? - Externals

https://externals.io/message/118311

ext/random における __unserialize() 実装が、どんな例外を投げるべきか?という相談

既存実装が結構バラバラ

ext/gmp: Exception
ext/hash: Exception
ext/date: Error
ext/spl: UnexpectedValueException
ext/random: Currently Exception.

POC がこちら

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

UnserializationFailedException が実装されています。

ksort breaking change - Externals

https://externals.io/message/118483

最近行われた ksort の修正について、これはバグフィックスではなくて BC Break じゃん。
まだリリースされていないから、一旦リバートしませんかしら?という zeriyoshi △の相談。

おれ、こんなこと思っても、びびってメール書かないね!(心の声)

でもって、現在進行中の話し合い

PHP 8.0 で導入された、下記の RFC に ksort が正しく追随していないというの Fix の理由でした。

https://wiki.php.net/rfc/string_to_number_comparison

そして、現状の PHP がその仕様に準じていないのだから、これは BC Break ではなく、正しい修正だという主張。
以後、Release Manager が議論に加わる。

RM Sara さんの見解

  1. ksort の挙動は修正されるべき -> これについて反対の人はいない
  2. マイナーリリース間の挙動は一貫性があり、予測可能でなければならない

そのため、8.0 については保守的にいって -> リバート
8.1 はアクティブにバグフィックスするから -> リバートしない

なんでやねん(心の声)

コレに対しては、同様にリバートして、8.2 で修正すべきだという意見が出ています。
8.2 ならどうせ、BC Break のテストするし。と

まだ議論続いております。


Bugs

Read of unset typed property /w magic __get throws wrong message · Issue #9388 · php/php-src https://github.com/php/php-src/issues/9388

セットされていない 型付きのプロパティにマジックメソッド __get でアクセスするとメッセージがおかしいというイシュー

Numbers starting with 0 fail validation using FILTER_VALIDATE_INT · Issue #9378 · php/php-src

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

0で始まる文字列は、octet とみなされるという仕様があるのです。

https://www.php.net/manual/ja/language.types.integer.php

しかし、これを見よ

https://3v4l.org/n9gAL

さらにこれを見よ

https://3v4l.org/c13Ad

00 は int なのか? int じゃないのか?どっちなのか?と

すまんな RFC 出してくれということでクローズ

(Bogus?) SSL error on ip.loltek.net · Issue #9390 · php/php-src

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

拙ブログにも書いた、この問題と同じに見えます。
https://blog.hanhans.net/2022/06/23/php-openssl3/

しかし、バージョンに関してはかなりセンシティブで、イシューでは以下の2つが上げられています。

  • PHP 8.1.8 OpenSSL/1.1.1n (PS curl is unaffected with the exact same OpenSSL)
  • PHP 8.1.2 OpenSSL/3.0.2 15 Mar 2022 (PS curl is unaffected with the exact same OpenSSL)

OpenSSL 3系に限ってないことから、PHP本体の不具合も考えられそうです。

8.1.7 に入った修正で Fix 済みということでやっぱりクローズ
https://github.com/php/php-src/pull/8558

Collision of interface constant and trait constant doesn't produce fatal error · Issue #9271 · php/php-src

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

Constant in Trait 関連

定数の競合が起きた場合の挙動について、既存に合わせようよという話を sji さんがされております。ニッコリ

I would still recommend sticking with the behavior as described in the RFC for the time being, and changing it later if necessary, in a consistent way with the behavior for properties :)

色々議論されていて、いったいどの挙動が正しいのやらという感じでしたが、RFC の定義通りにするという方向性で理解していれば良さそう。
つまり、下記の理解で正しいはず。まずは、目先の一貫性を大事にするというのは良いことだと思います。

<?php

abstract class A {
    public const CONSTANT = 1;
}

trait T {
    public const CONSTANT = 2;
}

// works well
class C1 extends A {
    public const CONSTANT = 2;
}

// fatal error
class C2 extends A {
    use T;
}

PHP 8.2 readonly classes allow inheriting mutable properties from traits · Issue #9285 · php/php-src

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

Readonly クラスが、ミュータブルなプロパティを trait 経由で保持できてしまう問題。

下記の条件でエラーとすることで決着。ちょっと determined の意味がよく飲み込めなかったのですのが、trait からの property が readonly じゃない場合はエラーという意味で読み替えて良いようです。

2 Making it an error to inherit a property from a trait at the time of inheritance when all trait properties are determined (including traits extending other traits)
EDIT: Or just non-readonly properties

RFC にも追記が入りました。Trait に Readonly でないプロパティが存在する場合、エラーになると書かれています。こっちはわかりやすい。

https://wiki.php.net/rfc/readonly_classes#errata

修正 PR はこちら

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

こんなエラーが出ます。

Fatal error: Readonly class C cannot use trait with a non-readonly property T::$prop in %s on line %d

Is it possible to integrate Composer into PHP · Issue #9393 · php/php-src

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

composer を php 本体に取り込んだらどうかな?というご意見

composer をマージするのはナンセンスだと思う。話し合うとしたら以下の観点かな?と上げられていたのがこれ

  • Should the manual have a composer section ?
  • Should the manual include references to composer in relevant sections ?
  • Should we provide updates on php.net for composer releases ?

でもって、こういうのを話し合うのは Github ではなく Internal だよ。というわけでクローズ

Crash in ZEND_RETURN/GC/zend_call_function · Issue #9323 · php/php-src

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

例によって、俺には分からんが修正されたやつ。

修正PR
https://github.com/php/php-src/commit/ba029fce6898cb50fd619b934e190ecf16b48835

SAVE_OPLINE ってのは必要だったらしい。

opcache.consistency_checks > 0 causes segfaults in PHP >= 8.1.5 in fpm context · Issue #8065 · php/php-src

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

まだ引き続き修正中。注視しましょう。

PHP 8.2.0-dev crashes on Apple Silicon with JIT turned on · Issue #9370 · php/php-src

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

Applie Silicon が JIT で SegV というイシュー

これが修正PR
https://github.com/php/php-src/pull/9371/files

PHP-FPM segfaults with Opcache enabled with Late Static Binding · Issue #9396 · php/php-src

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

php-fpm が Opcache 有効化状態で、遅延静的バインディングをすると SegV

Add an API to observe functions and classes being linked by bwoebi · Pull Request #9025 · php/php-src

https://github.com/php/php-src/pull/9025#issuecomment-1222196527

Link される関数やクラスを観察するAPIを作ろうというPR

こんな少量のコードで、可能なのですねという感想

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

これを必要とする人からコメントが入っていて、スレッドプログラミングとかで有用という意見。
しかし、コミッターの方々からは、否定的な意見が入っており、要観察

っていうか、機能追加だからRFC必要なんじゃないの???と思った。

が、マージされた。

exif read : warnings and errors : Potentially invalid endianess, Illegal IFD size and Undefined index · Issue #9397 · php/php-src

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

画像関連のイシュー。DJI の画像は、EXIF に標準じゃない形式で情報をいれてくるらしく。PHPではエラーになっている。

DJI の EXIF でコケて、画像全体が扱えなく成るのはバグ -> FIX対象
DJI の EXIF を上手に扱えるようにする -> これは別の話

Attempting to alias keywords results in a cryptic Parse error · Issue #9398 · php/php-src

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

<?php

use int as I;  //これはできる
use array as A;  //これはできない

array はキーワード
https://www.php.net/manual/en/reserved.keywords.php

int は予約語
https://www.php.net/manual/en/reserved.other-reserved-words.php

出来たところでつかえるわけではないのがミソ。

特別な予約後と、予約キーワードの扱いの違いにより、上記の挙動に違いが出ている。
array だと parse エラーになる。

Add a new zend API to check that strings don't have NUL bytes by Girgias · Pull Request #9375 · php/php-src

https://github.com/php/php-src/pull/9375#event-7233419252

NULL byte が含まれていないことを確認する API が追加されました。

zend_str_has_nul_byte

そもそもは、 ext/session のリファクタリングイシューから派生したものです。

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

Stop JIT hot spot counting by wxue1 · Pull Request #9343 · php/php-src

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

中身はピンとこないですが、JIT がもう最適化する余地が無いのに、HOT SPOT をカウントを続けても意味がないのでやめようというイシュー
きっと意味がないんだろうな。と思って読んだ。

Built in server with PHP_CLI_SERVER_WORKERS is broken in php > 8.0.2 · Issue #9400 · php/php-src

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

PHP_CLI_SERVER_WORKERS が2以上で、Built-in サーバーの挙動がおかしいというイシュー。

問題の出どころは下記のバグフィックスではないかと書かれています。

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

WORKERが複数プロセス存在しないと発生しないようです。実際に、イシューにはられているサンプルコードを実行すると、数個のリクエストがハングした状態になります。8.0.2 のバージョンでは発生しないものです。

Allow writing to readonly properties during cloning by nicolas-grekas · Pull Request #9403 · php/php-src

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

Readonly Poerperties を clone のときには解除しようという PR

コンセプトが良くわからないなと思っていた。

やり取り内では、RFC の Rationale(根拠) が参考リンクとして上げられていた。https://wiki.php.net/rfc/readonly_properties_v2#rationale

Once a property has been initialized, it cannot be changed under any circumstances.

つまり、clone でも Readonly プロパティは解除されるべきではないという解釈。
この方が、私も納得感がある。

JIT segmentation fault in PHP 8.1 · Issue #7817 · php/php-src

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

JIT 有効化で Segmentation Fault が出ているというイシュー

2021/12/23 からずっとやり取りが続いている。JITに関しては何本かのFixが取り込まれていて、修正は進んでいるけど、まだまだSegVが収まらない人がいる。

PgSQL large object resource is incorrectly closed · Issue #9411 · php/php-src

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

LOB のクローズタイミンがおかしいというイシュー。

イマイチぴんとこないが、修正PRはこれ

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

Randomizer::getInt(0, 2**32 - 1) with Mt19937 always returns 1 · Issue #9415 · php/php-src

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

表題のメソッドコールが、必ず1を返すというバグのイシュー

本当に1を返していた。この修正内容なら、理解できる

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

xmlRelaxNGCleanupTypes() is deprecated as of libxml2 2.10.0 by cmb69 · Pull Request #9417 · php/php-src

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

上位のライブラリーのAPI変更は、このようにして少しずつ修正されているんだなというイシュー。

Select rand_rangeXX() variant only based on the requested range by TimWolla · Pull Request #9418 · php/php-src

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

Randomizer のテストコード整理で見つかった不具合ということらしい。
32bit エンジン、64bit エンジンでの整合性を取るためのもの。(わかってない)

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

PgSQL large object resource is incorrectly closed · Issue #9411 · php/php-src

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

オープンした PgSQL の Large Object がトランザクション中にもかかわらず閉じられてしまっているというイシュー。
参考コードを見る限り、なぜクローズされているのかよくわからない。トランザクションの二回目を開始したことが影響しているのかもしれない。

修正PRはこちら

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

Large Object のクローズを行う関数を新設して、クローズの条件を細かく指定している。(ような気がする)

Store default object handlers alongside the class entry by bwoebi · Pull Request #9101 · php/php-src

https://github.com/php/php-src/pull/9101#issuecomment-1225986237

PHP 本体のリファクタリングというかんじでしょうか。

Native parameter attributes may not be used on promoted properties · Issue #9420 · php/php-src

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

Constructor Promotion されたパラメーターのアトリビュートが正常動作していないというイシュー。

ValueError: NumberFormatter::format(): Argument #3 must be a NumberFormatter::TYPE_* constant · Issue #9421 · php/php-src

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

NumberFormatter の format メソッドのエラーメッセージがおかしいというイシュー

バグが2つ隠れていて

  1. 第二引数のエラーなのに第三というエラーが出ている
  2. 第二引数はが、TYPE_CURRENCY の場合、formatCurrency を使えというエラーにするべき?

そもそも、通貨用の特別メソッドが存在しているので、通貨の場合は formatCurrency を使うのが筋のようです。
というわけで、不具合修正とドキュメント修正の両方が必要です。

Dynamic property deprecation warning/readonly error not emitted when modifying through new ArrayObject($targetObj); · Issue #9432 · php/php-src

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

ArrayObject を使って $y['foo'] のような形で dynamic property を作成した際に、deprecation が派出されないというイシュー

抜け穴を潰していく期間なので、こういうやつがポロポロ出てきています。

DateTime::getLastErrors() not returning false when no errors/warnings · Issue #9431 · php/php-src

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

DateTime::getLastErrors() はエラーがない場合は false を返すべきでは?というイシュー

現状は、空のエラーオブジェクトが返ってきています。ルールさえ決まっていれば、それで良いかなという気持ち。

RFC - json_validate() by juan-morales · Pull Request #9399 · php/php-src

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

現在、RFC が出されている json_validate の Pull Request です。
題材が実に分かりやすくて、ちょっとずつ指摘を受けて、PHPウェイな方向で実装修正されているので、めちゃくちゃ勉強になります。

これは、PHPソースコードリーディングの良い題材になりそうです。

array_key_exists on $GLOBALS takes linear time in PHP 8.1.0+ · Issue #9429 · php/php-src

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

array_key_exists の性能劣化に関する報告です。

1,000,000の値を持つ $GLOBALS に対して、実に 100000倍くらいの性能劣化が出ています。

https://3v4l.org/91CFl

array_key_exists がコールされるたびに $GLOBALS が再作成されているのが性能劣化の原因のようです。

この現象自体は、以下のコミットから入ったようです。

https://github.com/php/php-src/commit/3c68f38fdaec7a6f81f986a639bdd29716cf8f22

RFC はこちら

https://wiki.php.net/rfc/restrict_globals_usage

しかし、このRFCの目的は、$GLOBALS の参照というレアケースのために、配列処理全体でかかっている性能劣化を改善するものなので、
個人的には、これは求めていた結果になっているのではという気がするのですが。

そんなに早くしたかったら、普通の配列に詰め直したらという気もする。お試しコードはこちら。

https://3v4l.org/lkk0G#v8.1.9

Discussion