-
Notifications
You must be signed in to change notification settings - Fork 8k
Description
Description
There is a tricky Heisenberg JIT iterator bug.
It is reproducable with:
git clone https://github.com/phan/phan
cd phan
git checkout 07659073cc4fc8ef3ffa3ee67a49dde66b74d496
./testMake sure you have Nikita's php-ast extension installed.
Run ./test a few times with JIT enabled and you should see the crash eventually. Opcache settings are:
opcache.enable=On
opcache.enable_cli=On
opcache.jit=tracing # or any JIT mode
opcache.jit_buffer_size=128M
opcache.file_cache=/tmp/opcacheThe crash happens after these tests complete:
Phan\Tests\ForkPoolTest::testBasicForkJoinPhan\Tests\ForkPoolTest::testStartupFunctionPhan\Tests\PhanTest0 tests (0001_hello_world through 0011_duplicate_function)
It likely crashes during/after the 0012_closures.php test but I can't reproduce it by running an individual test. It somehow accumulates during multiple test runs.
Crash occurs in zend_iterator_unwrap when dereferencing corrupted object pointer:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055a1541314aa in zend_iterator_unwrap (array_ptr=array_ptr@entry=0x7fc847414bf1) at /home/rasmus/php-src/Zend/zend_iterators.c:102
102 if (Z_OBJ_HT_P(array_ptr) == &iterator_object_handlers) {
(gdb) bt
#0 0x000055a1541314aa in zend_iterator_unwrap (array_ptr=array_ptr@entry=0x7fc847414bf1) at /home/rasmus/php-src/Zend/zend_iterators.c:102
#1 0x000055a1540facec in zend_fe_fetch_object_helper_SPEC () at /home/rasmus/php-src/Zend/zend_vm_execute.h:3048
#2 0x000055a1541097a8 in ZEND_FE_FETCH_R_SPEC_VAR_HANDLER () at /home/rasmus/php-src/Zend/zend_vm_execute.h:23492
#3 execute_ex (ex=0x7fc847414bf1) at /home/rasmus/php-src/Zend/zend_vm_execute.h:118765
#4 0x000055a15410ccf0 in zend_execute (op_array=op_array@entry=0x7fc847498000, return_value=return_value@entry=0x0)
at /home/rasmus/php-src/Zend/zend_vm_execute.h:121436
#5 0x000055a15416bce6 in zend_execute_script (type=type@entry=8, retval=retval@entry=0x0, file_handle=file_handle@entry=0x7ffd9f935890)
at /home/rasmus/php-src/Zend/zend.c:1977
#6 0x000055a15400896f in php_execute_script_ex (primary_file=<optimized out>, retval=retval@entry=0x0) at /home/rasmus/php-src/main/main.c:2640
#7 0x000055a154008c87 in php_execute_script (primary_file=<optimized out>) at /home/rasmus/php-src/main/main.c:2680
#8 0x000055a15416d996 in do_cli (argc=argc@entry=2, argv=argv@entry=0x55a160de8dd0) at /home/rasmus/php-src/sapi/cli/php_cli.c:951
#9 0x000055a153a71433 in main (argc=2, argv=0x55a160de8dd0) at /home/rasmus/php-src/sapi/cli/php_cli.c:1362array_ptr points to invalid address 0x7fc847414bf1
(gdb) zbacktrace
[0x7fc8474149f0] Phan\Language\Element\Func->addParamsToScopeOfFunctionOrMethod(object[0x7fc847414a40], object[0x7fc847414a50], object[0x7fc847414a60],
object[0x7fc847414a70]) /home/rasmus/work/phan/src/Phan/Language/Element/FunctionTrait.php:792
[0x7fc847414960] Phan\Language\Element\Func->ensureScopeInitialized(object[0x7fc8474149b0])
/home/rasmus/work/phan/src/Phan/Language/Element/FunctionTrait.php:1274
[0x7fc8474148a0] Phan\Analysis->{closure:Phan\Analysis::analyzeFunctions():257}(object[0x7fc8474148f0]) /home/rasmus/work/phan/src/Phan/Analysis.php:267
[0x7fc847414770] Phan\Analysis->analyzeFunctions(object[0x7fc8474147c0], NULL) /home/rasmus/work/phan/src/Phan/Analysis.php:328
[0x7fc847414540] Phan\Phan->finishAnalyzingRemainingStatements(object[0x7fc847414590], NULL, array(1)[0x7fc8474145b0], array(0)[0x7fc8474145c0], NULL)
/home/rasmus/work/phan/src/Phan/Phan.php:575
[0x7fc847414360] Phan\Phan->analyzeFileList(object[0x7fc8474143b0], object[0x7fc8474143c0]) /home/rasmus/work/phan/src/Phan/Phan.php:468
[0x7fc847414190] Phan\Tests\AbstractPhanFileTest->testFiles(array(1)[0x7fc8474141e0], "./tests/files/expected/0012_closures.php.expected")
/home/rasmus/work/phan/tests/Phan/AbstractPhanFileTest.php:173
[0x7fc8474140d0] PHPUnit\Framework\TestCase->runTest() /home/rasmus/work/phan/vendor/phpunit/phpunit/src/Framework/TestCase.php:1617
[0x7fc847413ff0] PHPUnit\Framework\TestCase->runBare() /home/rasmus/work/phan/vendor/phpunit/phpunit/src/Framework/TestCase.php:1223
[0x7fc847413d50] PHPUnit\Framework\TestResult->run(object[0x7fc847413da0]) /home/rasmus/work/phan/vendor/phpunit/phpunit/src/Framework/TestResult.php:729
[0x7fc847413b00] PHPUnit\Framework\TestCase->run(object[0x7fc847413b50]) /home/rasmus/work/phan/vendor/phpunit/phpunit/src/Framework/TestCase.php:973
[0x7fc8474139b0] PHPUnit\Framework\TestSuite->run(object[0x7fc847413a00]) /home/rasmus/work/phan/vendor/phpunit/phpunit/src/Framework/TestSuite.php:685
[0x7fc847413860] PHPUnit\Framework\TestSuite->run(object[0x7fc8474138b0]) /home/rasmus/work/phan/vendor/phpunit/phpunit/src/Framework/TestSuite.php:685
[0x7fc847413710] PHPUnit\Framework\TestSuite->run(object[0x7fc847413760]) /home/rasmus/work/phan/vendor/phpunit/phpunit/src/Framework/TestSuite.php:685
[0x7fc8474135c0] PHPUnit\Framework\TestSuite->run(object[0x7fc847413610]) /home/rasmus/work/phan/vendor/phpunit/phpunit/src/Framework/TestSuite.php:685
[0x7fc847413320] PHPUnit\TextUI\TestRunner->run(object[0x7fc847413370], reference, reference, true)
/home/rasmus/work/phan/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:651
[0x7fc847413240] PHPUnit\TextUI\Command->run(array(1)[0x7fc847413290], true) /home/rasmus/work/phan/vendor/phpunit/phpunit/src/TextUI/Command.php:146
[0x7fc8474131a0] PHPUnit\TextUI\Command->main() /home/rasmus/work/phan/vendor/phpunit/phpunit/src/TextUI/Command.php:99
[0x7fc8474130a0] (main) /home/rasmus/work/phan/vendor/phpunit/phpunit/phpunit:107
[0x7fc847413020] (main) /home/rasmus/work/phan/vendor/bin/phpunit:122So it happens in src/Phan/Language/Element/FunctionTrait.php:790
$function_parameter_list = $function->getParameterList();
// ...
foreach ($function_parameter_list as $parameter) { // <- CRASH HERE (line 790)
$real_parameter_name_map[$parameter->getName()] = $parameter;
self::addParamToScopeOfFunctionOrMethod(...);
}It looks like the JIT corrupts the parameter list array/iterator during foreach iteration, causing zend_iterator_unwrap to dereference invalid memory. This is likely while Phan is analyzing closure parameters in test file tests/files/src/0012_closures.php
PHP Version
PHP 8.5.0-dev (cli) (built: Oct 14 2025 07:57:13) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.5.0-dev, Copyright (c) Zend Technologies
with Zend OPcache v8.5.0-dev, Copyright (c), by Zend Technologies
with php-ast installed
Operating System
Debian 13.1