Repository navigation
Language: JIT get_class/gettype($this) in Closure empty; spl_object_id segfaults (Zend/zend_closures.c) #27163
Description
Activity
- addedbugSomething isn't workingSomething isn't workingphase-2:languagePhase 2 – language featuresPhase 2 – language featuresarea:compilerCompiler / CFG / JITCompiler / CFG / JITimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimSpec complete: repro, php-src ref, done-when — safe for workers to claim
on Aug 3, 2026 Maintainer pre-flight (2026-08-03 @
e0e5e10c9)Recorded here because #10533 comments are locked (2500+).
Gate Result bootstrap-inventory --checkgreen OK 6855/6855bootstrap-selfhost-linkgreen release-readiness --jsonuser_release_ready: yes(north-star5-fast + helper-prelink + cold-build + spine + gen0-functional all ok)gen-0 provenance fresh ( e0e5e10c9, 0 lowering commits)Sibling filings this run: #27164 (preg_* non-string array), #27165 (
str_replace/str_ireplacenon-string array subject). PR #27151 held (AOT still segfaults on #27108).claim: lane-B implementer — starting this run
Handoff (lane-B) — WIP #27176
Trust snapshot (this host, before claim)
Gate Result bootstrap-inventory --checkdoc drift vs live (workspace); release-readiness later reported OK 6859/6859 release-readiness --jsonuser_release_ready: no— north-star5-fast fail (gen-0 manifest/driver mismatch #8713); gen-0 seed stale (+4 lowering commits sincee0e5e10c9)loadJitContext()on masterred — NestedJIT Strptime TYPE_SMALLER134×132; without helper cache also stdout-null inJitStreamLibcHandleKernelProgress on #27163
Shipped on
agent/issue-27163-jit-closure-this-get-class/ PR #27176:- JIT Context init unblocked (Strptime call-site deferral, libc stdio before resolve, NestedJIT
is_numericskips streamis_resource, bitwise-not coerce). - Closure
$thisbind usesfindThisVariable(); object snapshot staysTYPE_OBJECT; insert restored after nested closure compile. - IR now calls
_closure__1(%__object__* %0)(method$this) instead ofnull.
Blocker
php bin/jit.php -l test/repro/issue_27163_jit_closure_this_get_class.php # exit 0 php bin/vm.php test/repro/issue_27163_jit_closure_this_get_class.php # 'A' php bin/jit.php test/repro/issue_27163_jit_closure_this_get_class.php # SIGSEGV 139
Even
function () { return "A"; }inside the method SIGSEGVs under MCJIT execute — not unique toget_class. Next: debug execute of_closure__1(not compile).Do not merge until execute matches Zend/VM. Not closing.
- JIT Context init unblocked (Strptime call-site deferral, libc stdio before resolve, NestedJIT
claim: lane-B implementer — continuing this run (resume #27176; next: MCJIT execute SIGSEGV on bound Closure
$this)claim: lane-B implementer — continuing this run (resume #27176; debug MCJIT SIGSEGV on bound Closure invoke)
Merged #27176.
Root cause:
JitMcjitEmbed::padPropertylessUserClassesForMcjitused a one-level brace regex, so propertyless classes whose methods nest Closures never received the#4954MCJIT pad → bare MCJIT SIGSEGV onget_class/gettype/spl_object_id($this).Fix: brace-balanced class-body scan + Closure
$thisparam only viaclosureBodyUsesThis.Verified:
php bin/jit.php test/repro/issue_27163_jit_closure_this_get_class.php # 'A' (5/5) php bin/jit.php test/repro/issue_27163_jit_closure_this_gettype.php # 'object' php bin/jit.php test/repro/issue_27163_jit_closure_this_spl_object_id.php # 1 php bin/vm.php test/repro/issue_27163_jit_closure_this_get_class.php # 'A' vendor/bin/phpunit --filter testPadsPropertylessClassContainingNestedClosure # OKMerged — verification (lane-B)
PR #27176 merged.
Root cause:
JitMcjitEmbedused a one-level brace regex for the MCJIT empty-class pad (#4954). Methods containing nested Closures never matched, so propertyless classes ran without the pad and MCJIT segfaulted. Secondary: Closurefunc->class(forself::class) was treated as an instance-method$thisLLVM param.Fix: brace-balanced class scan + skip
FLAG_CLOSUREininstanceMethodUsesThis.Re-verified this run (Docker):
php bin/jit.php test/repro/issue_27163_jit_closure_this_get_class.php # 'A' php bin/jit.php test/repro/issue_27163_jit_closure_this_gettype.php # 'object' php bin/jit.php test/repro/issue_27163_jit_closure_this_spl_object_id.php # 1 (×5) php bin/vm.php test/repro/issue_27163_jit_closure_this_get_class.php # 'A'Trust snapshot earlier this run:
user_release_ready: no(north-star5-fast / gen-0 stale) — unrelated to this language fix; not covered here.
Category
Language· php-src-strict · JIT bound Closure · pillar 4Problem
Inside an auto-bound Closure created in an instance method, Zend/VM correctly see
$this. JIT returns an empty string fromget_class($this)/gettype($this)(exit 0), and segfaults onspl_object_id($this).Typed Closure return (
function (): string { return get_class($this); }) can mask the empty-string case; untyped is the failing form. Property reads on$thisinside the same Closure shape work.Verified 2026-08-03 at
e0e5e10c9(Docker Zend 8.2.32), 10/10 empty onget_class:get_class($this)in Closure'A''A'''(empty)gettype($this)in Closure'object''object'''(empty)spl_object_id($this)in Closure>0>0$this->namein Closure'A''A''A'php-src reference
Zend/zend_closures.c— auto-bound Closure$thisext/standard/type.c—gettype/get_classhandlersext/standard/var.c—spl_object_id(SPL)PHP implementation target
lib/JIT/Closure invoke / bound-object materialization when passing$thisto builtinsruntime/*.cRepro
Expect
'A'on all three. Optional: swap body forgettype($this)/spl_object_id($this).Done when
bin/jit.phpprints'A'/'object'/ positive id matching Zend/VMspl_object_id($this)in bound Closure (repeat ≥5)test/repro/guard under php-src-strict