php-src
Otherphp/php-src
The official PHP interpreter: a fast, pragmatic scripting engine for web development.
Overview
php-src is the reference implementation of PHP, a popular general-purpose scripting language especially suited to web development. Written in C, it includes the Zend Engine, a large set of bundled extensions, and an extensive test suite. PHP powers everything from personal blogs to some of the world's largest websites.
README Preview
\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)
TroubleshootingHow to fix 'memory leaks detected' in filters.c/dechunk filter when PHP file_get_contents fails on chunked HTTP response?
This is a confirmed bug in PHP's HTTP stream wrapper (reproduces on PHP 8.5.12 and master 8.7.0-dev). When a response uses Transfer-Encoding: chunked, the wrapper creates a dechunk filter during header parsing. If a later header line is malformed, the error path (out: label in php_stream_url_wrap_http_ex()) never frees the filter because the stream is NULL, leaking 96 bytes per failed request (80-byte filter struct + 16-byte dechunk data). Fix by patching ext/standard/http_fopen_wrapper.c in the out: cleanup section:
/* 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;
}
Add this right after efree(header_info.location); (around line 1230 on master). The patch is verified: repro reports 0 leaks and well-formed chunked responses are unaffected. Rebuild PHP from source after applying. If you cannot rebuild, the leaks are small (96 bytes/request) and only occur on malformed chunked responses, so disabling report_memleaks in production hides the symptom but does not fix the leak.
TroubleshootingWhy does PHP segfault with opcache.jit=1201 when passing a hooked property to a function?
This is a JIT compiler bug in PHP (GH-24398) affecting function JIT at optimization level 1 (opcache.jit=1201, 1211, 1101, 1251). When a property with a get hook is passed as an argument to a function resolved at runtime (e.g., declared conditionally or called unqualified from a namespace), the JIT mishandles ZEND_FETCH_OBJ_FUNC_ARG and crashes on the second call with a segfault (signal 11) or a UBSan null-pointer offset error in ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER. Fix: upgrade to a PHP version including the fix from GH-24402 (commit cfe77b82a6). Workarounds until then: set opcache.jit=disable, or switch to opcache.jit=tracing, or use a JIT level that does not trigger the bug such as 1202, 1205, or 1254.
TroubleshootingWhy does session_write_close() return true even when writing session data fails?
This is intended, documented behavior (see the Return Values section of the PHP manual for session_write_close()). The function returns false only when no session is active; it returns true in all other cases, including when the save handler's write() method fails. The failed write only triggers a warning like "session_write_close(): Failed to write session data using user defined save handler".
Workarounds to detect write failures:
1. In a custom SessionHandlerInterface implementation, record the return value of your own write() method (e.g., store it in a class property) and check it after session_write_close().
2. Catch the warning with an error handler:
$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();Do not rely on the
session_write_close() return value to detect write errors.TroubleshootingHow to fix PHP segfault (exit code 139) or zend_jit_trace_exit assertion failure with opcache tracing JIT?
This is a confirmed PHP bug (GH-24389) in the tracing JIT. When a function inlined in a hot trace is called with reference-bound variables and the operand type changes (e.g. int → float between iterations), the type guard emitted for register-allocated callee CVs on ZEND_JIT_TRACE_ENTER has no opline, so the trace exit reads an uninitialized EX(opline). Release builds segfault; debug builds abort with 'zend_jit_trace_exit: Assertion ... opline ... failed' in ext/opcache/jit/zend_jit_trace.c.
Fix: Upgrade PHP to a build that includes commit b4ca62e317 (PR GH-24411), which resolves the crash.
Workarounds if you cannot upgrade:
1. Disable the JIT while keeping OPcache: run with php -d opcache.enable_cli=1 -d opcache.jit=disable or set opcache.jit=disable in php.ini.
2. Avoid reference aliases ($xr = &$x, foreach ($data as &$v)) in hot loops whose values change type across calls (e.g. iterating an int array then a float array).
TroubleshootingWhy does PHP serialize() segfault or produce wrong back references when called from a __destruct() during another serialize()?
Root cause: PHP's serialize() is not reentrant. If a destructor fires while php_var_serialize_destroy() is tearing down the outer call's var_hash (e.g., an object only kept alive by the var_hash, or a GC cycle collected when it is released) and that destructor calls serialize(), the nested call reuses the outer var_hash. Consequences: (1) nested output gets wrong back references (r:N numbering continues from the outer call, e.g. r:6; instead of r:2;); (2) if the nested call grows the hash table, the outer destroy walks freed memory → use-after-free → Segmentation fault (exit 139) with backtrace in zval_ptr_dtor → zend_hash_destroy → php_var_serialize_destroy → zif_serialize. Confirmed on PHP 8.4.26 and 8.5.11 (NTS, official php Docker images); likely root cause of intermittent segfaults in test suites (e.g. TYPO3/PHPUnit where GC collects a DI container whose destructor serializes a cache entry). Workarounds until a PHP core fix lands: 1) Never call serialize() (or anything that may trigger it) inside __destruct() — defer/cache the work instead. 2) In test suites, call gc_collect_cycles(); immediately before serialize() so pending cyclic garbage and destructors run outside the serialization context. 3) Avoid letting objects be reachable only through the data being serialized. Reproducer: a class whose __destruct() calls serialize() on a large array, serialized inside another object via __serialize(), crashes reliably.