Repository navigation
Nested shm protections cause segfault #17246
Copy link
Copy link
Closed
Description
Description
The following code:
<?php
class Cycle
{
public function __construct()
{
$this->thing = function() use($obj) {};
}
public function __destruct()
{
}
}
for ($i = 0; $i < 10000; ++$i) {
$obj = new Cycle();
}
require __DIR__ . '/xpath_callables.inc';Resulted in this output:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1400489==ERROR: AddressSanitizer: SEGV on unknown address 0x0000418f412c (pc 0x7fce9acccbfa bp 0x7fff6704fae0 sp 0x7fff6704f6a0 T0)
==1400489==The signal is caused by a WRITE memory access.
#0 0x7fce9acccbfa in accel_new_interned_string /home/phpfuzz/WorkSpace/flowfusion/php-src/ext/opcache/ZendAccelerator.c:542:39
#1 0x7fce9ac16cd0 in zend_accel_persist_class_table_calc /home/phpfuzz/WorkSpace/flowfusion/php-src/ext/opcache/zend_persist_calc.c:581:3
#2 0x7fce9ac12ffe in zend_accel_script_persist_calc /home/phpfuzz/WorkSpace/flowfusion/php-src/ext/opcache/zend_persist_calc.c:632:2
#3 0x7fce9acfe31f in cache_script_in_shared_memory /home/phpfuzz/WorkSpace/flowfusion/php-src/ext/opcache/ZendAccelerator.c:1614:16
#4 0x7fce9aceab8a in persistent_compile_file /home/phpfuzz/WorkSpace/flowfusion/php-src/ext/opcache/ZendAccelerator.c:2168:24
#5 0x49f74b9 in compile_filename /home/phpfuzz/WorkSpace/flowfusion/php-src/Zend/zend_language_scanner.l:704:11
#6 0x46fa22b in zend_include_or_eval /home/phpfuzz/WorkSpace/flowfusion/php-src/Zend/zend_execute.c:5178:19
#7 0x42d3093 in ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER /home/phpfuzz/WorkSpace/flowfusion/php-src/Zend/zend_vm_execute.h:5247:17
#8 0x3f8fd47 in execute_ex /home/phpfuzz/WorkSpace/flowfusion/php-src/Zend/zend_vm_execute.h:58595:7
#9 0x3f91fcc in zend_execute /home/phpfuzz/WorkSpace/flowfusion/php-src/Zend/zend_vm_execute.h:64247:2
#10 0x4d2e029 in zend_execute_script /home/phpfuzz/WorkSpace/flowfusion/php-src/Zend/zend.c:1934:3
#11 0x3534c0a in php_execute_script_ex /home/phpfuzz/WorkSpace/flowfusion/php-src/main/main.c:2577:13
#12 0x3535d48 in php_execute_script /home/phpfuzz/WorkSpace/flowfusion/php-src/main/main.c:2617:9
#13 0x4d4233a in do_cli /home/phpfuzz/WorkSpace/flowfusion/php-src/sapi/cli/php_cli.c:938:5
#14 0x4d3c81f in main /home/phpfuzz/WorkSpace/flowfusion/php-src/sapi/cli/php_cli.c:1313:18
#15 0x7fcea25a9d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#16 0x7fcea25a9e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#17 0x605934 in _start (/home/phpfuzz/WorkSpace/flowfusion/php-src/sapi/cli/php+0x605934)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/phpfuzz/WorkSpace/flowfusion/php-src/ext/opcache/ZendAccelerator.c:542:39 in accel_new_interned_string
==1400489==ABORTING
To reproduce:
-d "opcache.protect_memory=1" -d "zwfusion/php-src/modules/opcache.so" -d "opcache.enable_cli=1" -d "opcache.jit=1254"
PHP Version
nightly
Operating System
No response
Activity
devnexen commentedon Dec 23, 2024
can't reproduce this one.
ndossche commentedon Dec 23, 2024
It reproduces for me.
ndossche commentedon Dec 23, 2024
But only reproduces with protect_memory on. I'll try to take a look.
ndossche commentedon Dec 23, 2024
Got distracted.
Anyway, this happens because of a nested
SHM_UNPROTECT()sequence.In particular we have the following sequence. Pay attention to the comments marked with
^^^.The reason this nesting happen is because:
cache_script_in_shared_memoryzend_optimize_scriptwill eventually run SCCP as part of the DFA pass.php-src/Zend/Optimizer/sccp.c
Lines 2387 to 2389 in 4e9cde7
In this case, this destruction invokes the tracing JIT, leading to the nested unprotects.
I see two possible solutions:
I think I prefer option 1 because it's more general and also not JITting would be a leaky abstraction.
[-]SEGV ext/opcache/ZendAccelerator.c:542:39 in accel_new_interned_string[/-][+]Nested shm protections cause segfault[/+]Fix phpGH-17246: Nested shm protections cause segfault
Fix GH-17246: GC during SCCP causes segfault
Merge branch 'PHP-8.3' into PHP-8.4
Merge branch 'PHP-8.4'