You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Opcache: SCCP turns $c::$m() into CONST/CONST INIT_STATIC_METHOD_CALL with one cache slot, heap-buffer-overflow #24252
With SCCP enabled and the compact-literals pass off, a dynamic static call whose class and method names are both constant-propagated reads past the function's runtime cache in ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER, and a release build segfaults.
opcache.optimization_level=0x7FFEBBFF (the default minus pass 11, 0x400) fails the same way. On an ASan build (run with USE_ZEND_ALLOC=0):
==282==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000003ed8 at pc 0x55a8609a58e4 bp 0x7ffe492d9390 sp 0x7ffe492d9380
READ of size 8 at 0x502000003ed8 thread T0
#0 0x55a8609a58e3 in ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER Zend/zend_vm_execute.h:7558
#1 0x55a860c28b6f in execute_ex Zend/zend_vm_execute.h:111556
#2 0x55a860c71830 in zend_execute Zend/zend_vm_execute.h:116021
0x502000003ed8 is located 0 bytes to the right of 8-byte region [0x502000003ed0,0x502000003ed8)
allocated by thread T0 here:
#4 0x55a86091962d in init_func_run_time_cache_i Zend/zend_execute.c:4511
#6 0x55a86097b67f in ZEND_INIT_FCALL_SPEC_CONST_HANDLER Zend/zend_vm_execute.h:4194
Expected sb, which is what the script prints with opcache off and at the default optimization level.
Found at commit b527e1b and still reproduces at 12df767. A release build segfaults (exit 139, no output) at both optimization levels above.
Looks like SCCP replaces the two operands one at a time: zend_optimizer_update_op1_const() (Zend/Optimizer/zend_optimizer.c:318-326) sees op2 still a CV and allocates one slot, then zend_optimizer_update_op2_const() (zend_optimizer.c:508-514) sees op1 already CONST and allocates nothing, while the CONST/CONST handler uses two slots (class and function). The default level hides it because pass 11 reallocates all cache slots.
I can send a patch if that helps.
Found with an LLM-based testing tool. As CONTRIBUTING.md asks, the paragraphs in > quotes were written with Claude; I ran every command myself.
@waroad I also found this after your first issue. The fix is already open. Is it possible your LLM has been reading the fix PR and is just rediscovering the same issues?
Please next time first check if #24237 covers this
No, it was found on its own: the test-generation run that hit it ran on Oct 9, before #24237 was opened. But I should have checked whether your open fix already covered it before filing, and I didn't. That's my mistake, sorry for the extra work. I'm adding a check against open fix PRs before anything else gets filed, so this won't happen again. Feel free to close this as covered by #24237.
Activity
ndossche commentedon Oct 11, 2026
@waroad I also found this after your first issue. The fix is already open. Is it possible your LLM has been reading the fix PR and is just rediscovering the same issues?
Please next time first check if #24237 covers this
waroad commentedon Oct 11, 2026
No, it was found on its own: the test-generation run that hit it ran on Oct 9, before #24237 was opened. But I should have checked whether your open fix already covered it before filing, and I didn't. That's my mistake, sorry for the extra work. I'm adding a check against open fix PRs before anything else gets filed, so this won't happen again. Feel free to close this as covered by #24237.