今週の PHP 2022/11/12 〜 2022/11/18
PHP のメーリングリストから、気になった情報をピックアップします。
Internal
[RFC] [Discussion] Readonly class amendments - Externals
ディスカッションのタイトルは「Readonly class の修正」です。
そもそもは、Readonly class のオブジェクト指向における立ち位置のようなものが議論されていましたが、RFC としてまとまりました。
修正案1 通常クラスが、readonly クラスを継承できるようにする。
現状は Fatal Error になります。
readonly class A {}
class B extends A {}
普遍のメンバを持ちつつ、動的なプロパティを利用する振る舞いを足すことも出来るということで、DTOの共通クラスのような扱いが期待されているのかもしれません。
修正案2 readonly なプロパティは、クローン時に再初期化可能
参考コードはこちら
class Foo {
public function __construct(
public readonly DateTime $bar,
public readonly DateTime $baz
) {}
public function __clone()
{
$this->bar = clone $this->bar; // Works
$this->cloneBaz();
}
public function cloneBaz()
{
$this->baz = clone $this->baz; // Also works
}
}
$foo = new Foo(new DateTime(), new DateTime());
$foo2 = clone $foo;
// No error, Foo::$bar and Foo::$baz are cloned deeply
clone 時にプロパティの値をいじれるようにする。ということでいいのかな。
サンプルを書いてみましたが、もちろん 8.2 系では動作しません。Cannot modify readonly property
が出ます。
再初期化は __clone
内でのみ可能というルールのようです。
コレなんの意味があるの?というと、deep-clone 出来るようにするというのが意図のようです。
例えば、通常のクラスであれば、RFC のサンプルのように Datetime
クラスのオブジェクトをプロパティに持つ場合は、__clone
を使うことで deep-copy を行うことができます。
object の ID が異なることに注目してください。readonly クラスではコレができません。つまり、同じオブジェクトを参照することになります。
何か困るのか?
readonly プロパティにセットされたのがミュータブルなオブジェクトの場合は、問題になりそうです。
つまり、clone 前後で同じオブジェクトを参照してしまうので、readonly なのに可変という状態になり、かつそれを阻止することができません。
ところで、なんで clone するんだろう... という疑問はさておき、修正内容については納得しました。
議論内では、現状の readonly クラスが LSP 違反であることも説明されていて、非常にためになる議論です。
Bugs
PHP unserialize bypass wakeup 8.1.1-fpm version · Issue #9936 · php/php-src
PHP-FPM で __wakeup
が bypass されて実行されるという脆弱性について。
これって、修正されてなかったっけ?
wakeup は unserialize されたときに実行される関数です。
元になった脆弱性はこちら
現行サポートの下限バージョンである、PHP 7.4 でも直っているはずのものではあります。
Fix GH-9883 SplFileObject::__toString() reads next line by Girgias · Pull Request #9912 · php/php-src
SplFileObject の __toString()
メソッドが、次行を読み込んでしまう不具合の修正です。
fgets してたんですねぇ。
Session name with . or [ silently fails instead of giving warning/error · Issue #9932 · php/php-src
こんなものが残っているんですね! .
または [
が含まられるセッション名だと、セッションが動かず、かつ Warning も Error も出ないという。
危ないやつなので、瞬殺されました。
次のリリースには入ると良いですね。
The behavior of mb_strcut in mbstring has been changed in PHP8.1 · Issue #9535 · php/php-src
mb_strcut
の挙動が ISO-2022-JP
に対しておかしくなっていた件ですが、修正コミットがマージ。
これも、次のリリース。
特に ISO-2022-JP
なんかは、使っているところがまだまだありそうなので、アップデート推奨。
preloading shutdown frees objects before module shutdown · Issue #9957 · php/php-src
preload している場合と、通常の場合で、object の解放と、モジュールのシャットダウンの順番が異なるというイシュー
実にありそうで、それでいて発見が難しそうなイシューです。
誰が見つけたのかと思ったら、 DataDog の tracer が rinit , rshutdown で動作しようとして SegV が出たということらしいです。
やはり、普通じゃないことをしないとこういうのは見つけられませんね。
unicode string corruption when using PDO_ODBC with FreeTDS 1.3.6 and MS SQL Server 2016 · Issue #9498 · php/php-src
Unicode 文字列が PDO_ODBC で崩れてしまうというイシュー。
FreeTDS は Sybase 系データベースのドライバーモジュールです。PHP から SQL Server に接続するときは、PDO_ODBC と FreeTDS という組み合わせで接続することになります。
select nchar
というのは、ユニコード文字列に対応した SELECT 構文らしいのですが、音符記号が正常に取れてません。
影響を受けるユーザー数は少なそうですが、つらそうなイシューです。
cmb69 さんによると、 https://github.com/php/php-src/issues/9828 こちらの件が、根本原因になっているらしい。
そして...
I don't see a way to properly fix this, so we're unfortunately stuck. :(
というわけで、迷宮入り。
その昔、FreeTDS 周りは、少し調べたことがあるので、もしかしたら、自分でもなにか手伝えるかもしれないので、9828 は詳しく見てみよう。
Promote unserialize() notices to warning by TimWolla · Pull Request #9629 · php/php-src
2/3 が可決されました。
というわけで、さっそくマージされています。8.3 向けの Feature ですね。
PHP 8.1 bug, segfault executing Wordpress plugin code · Issue #9961 · php/php-src
8.1 で Wordpress のプラグイン実行時に SegV とのこと。該当の Wordpress のコードは普通の DB接続に見えます。一体何が原因なのか?
It is recommended to add the function of assigning object types to variables · Issue #9962 · php/php-src
Mixedな戻り値に対して、呼び元で型指定出来るようにしようよ!というイシュー
記法としては Alias みたいなやつですね。RFCを出してねで終了。
class A{}
$var = serialize(new A());
$a = unserialize($var) as `\A::class;`
下は、現状で使える解決策のコード例です。
var コメントを使ったり、assert を使ったりすることで、IDE の補完や、型安全を保証できます。
Non-pure default arguments are mistakenly cached · Issue #9965 · php/php-src
Non-pure というのは、インスタンスに文字列結合した状態のことを指すようです。
文字列結合をやめると、正常に動くようになります。
Non-pure なはずなのに、pure と判断されるため、再評価されず static 変数がカウントアップされないということなのかな?
修正内容は、今の自分には理解できません。
Segmentation Fault during OPCache Preload in PHP 8.1+ · Issue #9968 · php/php-src
OPCache Preload の SegV 報告です。
再現コードも添付されており、実際に SegV が確認できます。
Preload なのか、JIT の問題なのか。
JIT の問題の場合は設定で逃れることも可能だといいですね。
mb_ereg_search_pos fails test "start of string" when using mb_ereg_search_setpos · Issue #9970 · php/php-src
近年は、UTF8 オプションをつけた preg 関数を使うことが多いので、 mb_ereg_search_pos
なんてあったっけ?という感じです。
そこに、使ったこともない mb_ereg_search_setpos
が組み合わさっているので、理解が難しい。
mb_ereg は、鬼車が使われているので、正規表現のパターンも鬼車に準拠していそうですが、^
の解釈はどうなっているのか?
しばらく観察します。
Use fast text conversion filters to implement mb_convert_variables by alexdowad · Pull Request #9966 · php/php-src
mb_convert_variables
の速度改善のようです。
行われている内容は、まじでよくわからない。やはり Valgrind が必要なのか......
Discussion