[php-src] PR #25298: JIT: Fix FETCH_DIM_IS ignoring leading-numeric string offsets

From: Date: Sat, 07 Nov 2026 22:44:09 +0000
Subject: [php-src] PR #25298: JIT: Fix FETCH_DIM_IS ignoring leading-numeric string offsets
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-40416@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/25298 Author: jorgsowa For a leading-numeric string offset such as "1x", the VM warns Illegal string offset "1x" and uses the leading number, also under ??: ``` function f(string $s) { return $s["1x"] ?? "default"; } var_dump(f("abc")); // VM: Warning: Illegal string offset "1x" + string(1) "b" // JIT: string(7) "default", no warning ``` This is the behaviour specified by the Saner Numeric Strings RFC and pinned in Zend/tests/offsets/string_container_offset_behaviour.phpt. The RFC change (b2248789ed2) updated the JIT's R helper but not zend_jit_fetch_dim_str_is_helper, which kept a strict parse and silently returned null. The IS helper now parses the offset like the VM, warns on trailing data, and holds a reference to the string in case the error handler releases it. zend_may_throw_ex() did not count this warning for FETCH_DIM_IS either. With ?? this has no effect, because COALESCE always consumes the result. The inner fetch of a nested isset($s["1x"][0]) / empty() is different: - DCE removed it when the result was unused, losing the warning even without JIT. - Function JIT skipped saving the call chain around it, leaking already-sent arguments when the error handler throws. | Code | VM (no opcache) | opcache, JIT off | opcache, function JIT | |---|---|---|---| | $s["1x"] ?? "d" | warning, "b" | warning, "b" | before: "d", no warning<br>after: warning, "b" | | $x = isset($s["1x"][0]); (result used) | warning, true | warning, true | before: false, no warning<br>after: warning, true | | isset($s["1x"][0]); (result unused) | warning | before: no warning<br>after: warning | before: no warning<br>after: warning | | consume($t, isset($s["1x"][0])) with a throwing error handler | exception | exception | before: exception plus a leaked $t<br>after: exception |

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