Skip to content

Commit f9fd505

Browse files
morrisonleviclaude
andcommitted
Fix TAILCALL delayed helper interrupt via call_interrupt_op sentinel
In TAILCALL delayed helpers (EX-signature helpers that can't musttail), ZEND_VM_INTERRUPT() was routing through zend_interrupt_helper_SPEC, which can return a tagged pointer (ZEND_VM_ENTER_BIT set) via ZEND_VM_ENTER(). That tagged pointer propagated back to ZEND_VM_DISPATCH_TO_HELPER, which blindly dispatched to it, causing a misaligned access crash. The fix: TAILCALL delayed helpers use SAVE_OPLINE() + return &call_interrupt_op, the sentinel pattern already used by TAILCALL VM. ZEND_VM_DISPATCH_TO_HELPER then dispatches to call_interrupt_op->handler (zend_interrupt_helper_SPEC_TAILCALL), which loads the real opline from EX(opline) and handles the interrupt cleanly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0c31be1 commit f9fd505

2 files changed

Lines changed: 10 additions & 6 deletions

File tree

Zend/zend_vm_execute.h

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Zend/zend_vm_gen.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,10 +1867,12 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
18671867
out($f, "#pragma push_macro(\"ZEND_VM_INTERRUPT\")\n");
18681868
out($f, "#undef ZEND_VM_INTERRUPT\n");
18691869
out($f, "#define ZEND_VM_CONTINUE(handler) return opline\n");
1870-
out($f, "#if !(defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)) && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL\n");
1871-
out($f, "# define ZEND_VM_INTERRUPT() return zend_interrupt(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
1872-
out($f, "#else\n");
1870+
out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL\n");
1871+
out($f, "# define ZEND_VM_INTERRUPT() SAVE_OPLINE(); return &call_interrupt_op;\n");
1872+
out($f, "#elif defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
18731873
out($f, "# define ZEND_VM_INTERRUPT() return zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
1874+
out($f, "#else\n");
1875+
out($f, "# define ZEND_VM_INTERRUPT() return zend_interrupt(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
18741876
out($f, "#endif\n");
18751877
out($f, $delayed_helpers);
18761878
out($f, "#pragma pop_macro(\"ZEND_VM_INTERRUPT\")\n");

0 commit comments

Comments
 (0)