Category
bug · AOT crash · leftover of #27028 / peer #34243 NestedJIT
Problem
mb_substr() / mb_strcut() AOT binaries SIGSEGV (exit 139) when the start/from offset is a runtime integer. Literal offsets fold at compile time and work. VM and Zend match.
Probed 2026-08-23 @ master vs Zend 8.2 (aot-smoke 8/8 first).
| Repro |
Zend |
AOT |
mb_substr("über", 1, 2) |
string(2) "be" |
string(2) "be" |
$i=1; mb_substr("über", $i, 2) |
string(2) "be" |
SIGSEGV |
$s="über"; mb_substr($s, 1, 2) |
string(2) "be" |
string(2) "be" |
$s="über"; $i=1; mb_strcut($s, $i, 2) |
string(2) "ü" |
SIGSEGV |
Root shape matches #34243 / #34146: NestedJIT helper call without JitNestedHelperCoerce::callHelper — runtime int ABI mismatch. Helpers also call VmMbstring::{substr,strcut} which NestedJIT misbehaves on (peer MbChrOrdJitHelper).
php-src reference
PHP implementation target
ext/mbstring/mb_substr.php (JitMbSubstr) + ext/mbstring/JitMbStrcut.php — route through JitNestedHelperCoerce::callHelper
ext/mbstring/MbStrcutJitHelper.php — NestedJIT-safe UTF-8 peel (no VmMbstring::*)
Repro
./script/docker-exec.sh -- bash -lc 'printf "%s\n" "<?php \$i=1; var_dump(mb_substr(\"über\", \$i, 2));" > /tmp/r.php && php bin/compile.php -o /tmp/r.bin /tmp/r.php && /tmp/r.bin'
Done when
Category
bug· AOT crash · leftover of #27028 / peer #34243 NestedJITProblem
mb_substr()/mb_strcut()AOT binaries SIGSEGV (exit 139) when the start/from offset is a runtime integer. Literal offsets fold at compile time and work. VM and Zend match.Probed 2026-08-23 @
mastervs Zend 8.2 (aot-smoke8/8 first).mb_substr("über", 1, 2)string(2) "be"string(2) "be"$i=1; mb_substr("über", $i, 2)string(2) "be"$s="über"; mb_substr($s, 1, 2)string(2) "be"string(2) "be"$s="über"; $i=1; mb_strcut($s, $i, 2)string(2) "ü"Root shape matches #34243 / #34146: NestedJIT helper call without
JitNestedHelperCoerce::callHelper— runtime int ABI mismatch. Helpers also callVmMbstring::{substr,strcut}which NestedJIT misbehaves on (peer MbChrOrdJitHelper).php-src reference
ext/mbstring/mbstring.c—PHP_FUNCTION(mb_substr),PHP_FUNCTION(mb_strcut)PHP implementation target
ext/mbstring/mb_substr.php(JitMbSubstr) +ext/mbstring/JitMbStrcut.php— route throughJitNestedHelperCoerce::callHelperext/mbstring/MbStrcutJitHelper.php— NestedJIT-safe UTF-8 peel (noVmMbstring::*)Repro
./script/docker-exec.sh -- bash -lc 'printf "%s\n" "<?php \$i=1; var_dump(mb_substr(\"über\", \$i, 2));" > /tmp/r.php && php bin/compile.php -o /tmp/r.bin /tmp/r.php && /tmp/r.bin'Done when
mb_substr/mb_strcutmatch Zend (no SIGSEGV)./script/aot-smoke.shstays 8/8