概要
php-src は PHP 言語のリファレンス実装です。PHP は人気のある汎用スクリプト言語であり、特に Web 開発に適しています。このプロジェクトは C 言語で記述されており、Zend エンジン、多数の組み込み拡張機能、充実したテストスイートを含み、個人ブログから世界の大規模ウェブサイトに至るまで、さまざまなアプリケーションを支えています。
README プレビュー
\n \n \n \n\n\n# The PHP Interpreter\n\nPHP is a popular general-purpose scripting language that is especially suited to\nweb development. Fast, flexible and pragmatic, PHP powers everything from your\nblog to the most popular websites in the world.\n\nPHP is distributed under the [Modified BSD License](LICENSE)\n(SPDX-License-Identifier: `BSD-3-Clause`).\n\n[](https://github.com/php/php-src/actions/workflows/test.yml)\n[](https://issues.oss-fuzz.com/issues?q=project:php)\n\n## Documentation\n\nThe PHP manual is available at [php.net/docs](https://www.php.net/docs).\n\n## Installation\n\n### Prebuilt packages and binaries\n\nPrebuilt packages and binaries can be used to get up and running fast with PHP.\n\nFor Windows, the PHP binaries can be obtained from\n[windows.php.net](https://windows.php.net). After extracting the archive the\n`*.exe` files are ready to use.\n\nFor other systems, see the [installation chapter](https://www.php.net/install).\n\n### Building PHP source code\n\n*For Windows, see [Build your own PHP on Windows](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2).*\n\nFor a minimal PHP build from Git, you will need autoconf, bison, and re2c. For\na default build, you will additionally need libxml2 and libsqlite3.\n\nOn Ubuntu, you can install these using:\n\n```shell\nsudo apt install -y pkg-config build-essential autoconf bison re2c libxml2-dev libsqlite3-dev\n```\n\nOn Fedora, you can install these using:\n\n```shell\nsudo dnf install re2c bison autoconf make ccache libxml2-devel sqlite-devel\n```\n\nOn MacOS, you can install these using `brew`:\n\n```shell\nbrew install autoconf bison re2c libiconv libxml2 sqlite\n```\n\nor with `MacPorts`:\n\n```shell\nsudo port install autoconf bison re2c libiconv libxml2 sqlite3\n```\n\nGenerate configure:\n\n```shell\n./buildconf\n```\n\nConfigure your build. `--enable-debug` is recommended for development, see\n`./configure --help` for a full list of options.\n\n```shell\n# For develo
FAQ (5)
トラブル対応PHP の file_get_contents がチャンク化された HTTP レスポンスで失敗した場合に、filters.c/dechunk フィルターで発生する 'memory leaks detected' を修正する方法
これは PHP の HTTP ストリームラッパーにおける確認済みのバグです(PHP 8.5.12 および master 8.7.0-dev で再現します)。レスポンスが Transfer-Encoding: chunked を使用する場合、ラッパーはヘッダー解析中に dechunk フィルターを作成します。後続のヘッダー行が不正な形式の場合、ストリームが NULL であるため、エラーパス(php_stream_url_wrap_http_ex() 内の out: ラベル)ではフィルターが解放されず、失敗したリクエストごとに 96 バイト(80 バイトのフィルター構造体 + 16 バイトの dechunk データ)がリークします。ext/standard/http_fopen_wrapper.c の out: クリーンアップセクションにパッチを適用して修正します:
/* On the error path stream is NULL and the filter is never appended
* to readfilters below, so it must be freed here. */
if (header_info.transfer_encoding != NULL && stream == NULL) {
php_stream_filter_free(header_info.transfer_encoding);
header_info.transfer_encoding = NULL;
}
これを efree(header_info.location); の直後(master では 1230 行目付近)に追加してください。このパッチは検証済みです:再現テストではリークが 0 と報告され、正常な形式の chunked レスポンスには影響がありません。適用後、PHP をソースから再ビルドしてください。再ビルドできない場合、リークは小さく(96 バイト/リクエスト)、不正な形式の chunked レスポンスでのみ発生するため、本番環境で report_memleaks を無効にすれば症状は隠れますが、リーク自体は修正されません。
トラブル対応hooked propertyを関数に渡すと、opcache.jit=1201でPHPがセグフォルトするのはなぜですか?
これは PHP における JIT コンパイラのバグ(GH-24398)で、最適化レベル 1(opcache.jit=1201, 1211, 1101, 1251)の function JIT に影響します。get フックを持つプロパティが、実行時に解決される関数(例:条件付きで宣言された関数や、名前空間から非修飾名で呼び出される関数)の引数として渡された場合、JIT は ZEND_FETCH_OBJ_FUNC_ARG を誤って処理し、2 回目の呼び出しでセグメンテーションフォルト(signal 11)、または ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER における UBSan の null ポインタオフセットエラーによってクラッシュします。修正方法:GH-24402(コミット cfe77b82a6)の修正を含む PHP バージョンにアップグレードしてください。それまでの回避策:opcache.jit=disable に設定するか、opcache.jit=tracing に切り替えるか、1202、1205、1254 など、このバグが発生しない JIT レベルを使用してください。
トラブル対応セッションデータの書き込みに失敗した場合でも、session_write_close() が true を返すのはなぜですか?
これは意図された、ドキュメントに記載されている動作です(session_write_close() の PHP マニュアルの「返り値」セクションを参照してください)。この関数は、セッションがアクティブでない場合にのみ false を返します。セーブハンドラの write() メソッドが失敗した場合を含め、それ以外のすべてのケースでは true を返します。書き込みの失敗は、「session_write_close(): Failed to write session data using user defined save handler」のような警告を発生させるだけです。
書き込みの失敗を検出するための回避策:
1. カスタムの SessionHandlerInterface 実装において、独自の write() メソッドの戻り値を記録し(例えば、クラスのプロパティに保存する)、session_write_close() の後でそれを確認します。
2. エラーハンドラで警告を捕捉します:
$writeFailed = false;
set_error_handler(function ($no, $msg) use (&$writeFailed) {
if (str_contains($msg, 'Failed to write session data')) { $writeFailed = true; }
return true;
});
session_write_close();
restore_error_handler();書き込みエラーの検出に
session_write_close() の戻り値を頼らないでください。トラブル対応opcache tracing JIT で発生する PHP セグフォルト (終了コード 139) または zend_jit_trace_exit アサーション失敗を修正する方法
これはトレーシング JIT における確認済みの PHP バグ (GH-24389) です。ホットトレース内でインライン化された関数が参照にバインドされた変数とともに呼び出され、オペランドの型が変化した場合 (例: イテレーション間で int → float に変わる場合)、ZEND_JIT_TRACE_ENTER でレジスタに割り当てられた callee の CV に対して生成される型ガードには opline が含まれないため、トレースイグジットが未初期化の EX(opline) を読み取ります。リリースビルドではセグメンテーションフォルトが発生し、デバッグビルドでは ext/opcache/jit/zend_jit_trace.c において 'zend_jit_trace_exit: Assertion ... opline ... failed' により中断 (abort) します。
修正: コミット b4ca62e317 (PR GH-24411) を含むビルドへ PHP をアップグレードしてください。これによりクラッシュが解消されます。
アップグレードできない場合の回避策:
1. OPcache を有効にしたまま JIT を無効化する: php -d opcache.enable_cli=1 -d opcache.jit=disable で実行するか、php.ini に opcache.jit=disable を設定してください。
2. 呼び出し間で値の型が変化するホットループ (例: int 配列をイテレートした後に float 配列をイテレートする場合) では、参照エイリアス ($xr = &$x、foreach ($data as &$v)) を避けてください。
トラブル対応なぜ、別の serialize() の実行中に __destruct() から serialize() を呼び出すと、セグフォルトが発生したり、誤ったバック参照が生成されたりするのですか?
根本原因: PHP の serialize() はリエントラントではありません。php_var_serialize_destroy() が外側の呼び出しの var_hash を破棄している最中に(例: var_hash によってのみ生存しているオブジェクト、またはそれが解放された際に回収される GC サイクル)、デストラクタが発火し、そのデストラクタが serialize() を呼び出すと、ネストした呼び出しは外側の var_hash を再利用します。結果: (1) ネストした出力が誤ったバックリファレンスを持ちます(r:N の番号付けが外側の呼び出しから継続し、例えば r:2; ではなく r:6; になります)。(2) ネストした呼び出しがハッシュテーブルを拡張すると、外側の destroy が解放済みメモリを走査します → use-after-free → Segmentation fault (exit 139) が発生し、バックトレースは zval_ptr_dtor → zend_hash_destroy → php_var_serialize_destroy → zif_serialize となります。PHP 8.4.26 および 8.5.11(NTS、公式 php Docker イメージ)で確認済みです。テストスイートにおける断続的な segfault(例: TYPO3/PHPUnit で、GC が DI コンテナを回収し、そのデストラクタがキャッシュエントリをシリアライズするケース)の根本原因である可能性が高いです。PHP コアの修正が入るまでの回避策: 1) __destruct() 内で serialize()(またはそれを発動させる可能性のあるもの)を決して呼び出さないこと — 代わりに処理を延期またはキャッシュしてください。2) テストスイートでは、serialize() の直前に gc_collect_cycles(); を呼び出し、保留中の循環ガベージとデストラクタがシリアライゼーションコンテキストの外で実行されるようにしてください。3) オブジェクトがシリアライズ対象のデータを通じてのみ到達可能にならないようにしてください。再現方法: __destruct() が大きな配列に対して serialize() を呼び出すクラスを、__serialize() 経由で別のオブジェクト内でシリアライズすると、確実にクラッシュします。