[php-src] PR #23545: Fix IS_IDENTICAL_EMPTY_ARRAY specialization for an IS_CONST op1

From: Date: Wed, 02 Sep 2026 15:20:33 +0000
Subject: [php-src] PR #23545: Fix IS_IDENTICAL_EMPTY_ARRAY specialization for an IS_CONST op1
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38267@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/23545 Author: Mrmaxmeier Hi, we ran into an assertion failure in the VM with the fuzzer-function-jit fuzzing target: ```php <?php if (A::class->p === []) { echo "identical\n"; } if (A::class->p !== []) { echo "not identical\n"; } echo "OK\n"; ``` On a debug build this aborts in _get_zval_ptr_tmpvarcv(). ZEND_IS_IDENTICAL_EMPTY_ARRAY is new in 8.5, so this does not affect 8.4. <details> <summary>Assertion backtrace for reproducer</summary> ``` /out/php-fuzz-function-jit: Running 1 inputs 100 time(s) each. Running: /testcase php-fuzz-function-jit: /src/php-src/Zend/zend_execute.c:402: zval *_get_zval_ptr_tmpvarcv(int, znode_op, int, zend_execute_data *): Assertion `op_type == (1<<3)' failed. AddressSanitizer:DEADLYSIGNAL ================================================================= ==15==ERROR: AddressSanitizer: ABRT on unknown address 0x00000000000f (pc 0x7fd4f89f000b bp 0x7fd4f8b65588 sp 0x7fff42d4cc30 T0) SCARINESS: 10 (signal) #0 0x7fd4f89f000b in raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d) #1 0x7fd4f89cf858 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x22858) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d) #2 0x7fd4f89cf728 (/lib/x86_64-linux-gnu/libc.so.6+0x22728) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d) #3 0x7fd4f89e0fd5 in __assert_fail (/lib/x86_64-linux-gnu/libc.so.6+0x33fd5) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d) #4 0x56412dbacdc3 in _get_zval_ptr_tmpvarcv /src/php-src/Zend/zend_execute.c:402:3 #5 0x56412dbacdc3 in ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_HANDLER /src/php-src/Zend/zend_vm_execute.h:14529:8 #6 0x56412df140bb in fuzzer_execute_ex /src/php-src/sapi/fuzzer/fuzzer-execute-common.h:65:12 #7 0x56412da3813d in zend_execute /src/php-src/Zend/zend_vm_execute.h:115989:2 #8 0x56412df153bf in fuzzer_do_request_from_buffer /src/php-src/sapi/fuzzer/fuzzer-sapi.c:293:5 #9 0x56412df13954 in LLVMFuzzerTestOneInput /src/php-src/sapi/fuzzer/fuzzer-function-jit.c:32:2 [..] DEDUP_TOKEN: raise--abort-- SUMMARY: AddressSanitizer: ABRT (/lib/x86_64-linux-gnu/libc.so.6+0x4300b) (BuildId: 5792732f783158c66fb4f3756458ca24e46e827d) in raise ==15==ABORTING ``` </details> The ZEND_IS_IDENTICAL_EMPTY_ARRAY / ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY specializations are declared for the operand pair TMPVARCV, CONST: ```c ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op2_type == IS_CONST && (...), ZEND_IS_IDENTICAL_EMPTY_ARRAY, TMPVARCV, CONST, ...) ``` but the condition that selects them only ever looked at op2. The other specializations of these opcodes bail out for a CONST/CONST operand pair, this one did not. So an IS_CONST op1 still selected a handler that reads its op1 through _get_zval_ptr_tmpvarcv(), which cannot read a literal and asserts. Getting there needs the optimizer: type inference proves the property fetch on the A::class string to be null and substitutes the constant into op1, but the comparison itself is not folded, which leaves a ZEND_IS_IDENTICAL with two IS_CONST operands for the specializer to look at. The fix adds the missing op->op1_type != IS_CONST to the selection condition of both handlers, which is what the sibling specializations already do. Thanks! --- _Found by the CISPA Fandango team while triaging findings in oss-fuzz harnesses._

« previous php.git-pulls (#38267) next »