Skip to content

Commit 5e09eb5

Browse files
ondrejmirtesclaude
andcommitted
Read PHP 8.6 thread-safe EG() and CG() through the exported offsets
PHP 8.6's thread-safe headers compute the offset of the executor and compiler globals from sizeof(zend_executor_globals) and sizeof(zend_compiler_globals), and EG()/CG() compile that constant into every use. The module API number does not guard those sizes: 8.6.0RC4 appended `delayed_oom` to the executor globals (php-src 3584a98bda0, a security fix), so an extension built against RC3's headers read and wrote every EG() field 32 bytes off and crashed on startup. Redefine EG() and CG() to go through executor_globals_offset and compiler_globals_offset, which the engine exports, as the headers do up to 8.5. The redefinition comes before the rest of the engine headers, so their inline functions use it too. Only the version-specific objects change; the shared core compiles to the same code as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0135ph8YpHvnbDwd4G6rozNY
1 parent 528358e commit 5e09eb5

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

‎turbo-ext/src/support.h‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,27 @@
2929
* every gcc/libc target supports — gcc then warns the attribute is ignored */
3030
#pragma GCC diagnostic ignored "-Wattributes"
3131

32+
extern "C" {
33+
#include "php_version.h"
34+
#include "zend_globals_macros.h"
35+
}
36+
37+
/* PHP 8.6's thread-safe EG() and CG() reach the globals at an offset the
38+
* headers compute from sizeof(zend_executor_globals) and
39+
* sizeof(zend_compiler_globals) — a constant compiled into every use, which
40+
* the module API number does not guard: 8.6.0RC4 appended a field to the
41+
* executor globals, and an extension built against RC3's headers read and
42+
* wrote every EG() field 32 bytes off. Read through the offsets the engine
43+
* exports instead, as the headers do up to 8.5, so a field appended by a
44+
* later release moves nothing. Redefined before the rest of the headers, so
45+
* their inline functions get it too. */
46+
#if defined(ZTS) && PHP_VERSION_ID >= 80600
47+
#undef EG
48+
#undef CG
49+
#define EG(v) ZEND_TSRMG_FAST(executor_globals_offset, zend_executor_globals *, v)
50+
#define CG(v) ZEND_TSRMG_FAST(compiler_globals_offset, zend_compiler_globals *, v)
51+
#endif
52+
3253
extern "C" {
3354
#include "php.h"
3455
#include "zend_exceptions.h"

0 commit comments

Comments
 (0)