Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Zend/zend_vm_execute.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions Zend/zend_vm_gen.php
Original file line number Diff line number Diff line change
Expand Up @@ -1917,7 +1917,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"static const zend_op call_interrupt_op;\n");
out($f,"#endif\n\n");
}
out($f,"#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) || !ZEND_VM_SPEC\n");
out($f,"#if ZEND_VM_KIND != ZEND_VM_KIND_HYBRID || !ZEND_VM_SPEC\n");
out($f,"static zend_vm_opcode_handler_t zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op);\n");
out($f,"#endif\n\n");
if ($kind == ZEND_VM_KIND_HYBRID) {
Expand Down Expand Up @@ -2146,6 +2146,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"# undef ZEND_VM_INTERRUPT\n");
out($f,"# undef ZEND_VM_ENTER_EX\n");
out($f,"# undef ZEND_VM_LEAVE\n");
out($f,"# undef ZEND_VM_DISPATCH\n");
out($f,"\n");
out($f,"# define ZEND_VM_TAIL_CALL(call) ZEND_MUSTTAIL return call\n");
out($f,"# define ZEND_VM_CONTINUE() ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n");
Expand All @@ -2159,6 +2160,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n");
out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
out($f,"# define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n");
out($f,"\n");
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS);\n");
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt(ZEND_OPCODE_HANDLER_ARGS);\n");
Expand Down Expand Up @@ -3042,7 +3044,7 @@ function gen_vm($def, $skel) {
out($f, "\treturn (spec & SPEC_START_MASK) + offset;\n");
}
out($f, "}\n\n");
out($f, "#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) || !ZEND_VM_SPEC\n");
out($f, "#if ZEND_VM_KIND != ZEND_VM_KIND_HYBRID || !ZEND_VM_SPEC\n");
out($f, "static zend_vm_opcode_handler_t zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op)\n");
out($f, "{\n");
if (!ZEND_VM_SPEC) {
Expand Down
24 changes: 24 additions & 0 deletions ext/zend_test/tests/gh24081.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
GH-24081 (User opcode handlers resume execution against a stale frame under ZEND_VM_KIND_TAILCALL)
--EXTENSIONS--
zend_test
--INI--
opcache.jit=disable
zend_test.observer.enabled=1
zend_test.observer.show_opcode_in_user_handler=ZEND_ADD
--FILE--
<?php
function f($a, $b) {
$r = $a + $b;
return strlen("x") + $r;
}

var_dump(f(1, 2));
?>
--EXPECTF--
<!-- init '%s' -->
<!-- init f() -->
<!-- opcode: 'ZEND_ADD' in user handler -->
<!-- opcode: 'ZEND_ADD' in user handler -->
<!-- init var_dump() -->
int(4)
Loading