[php-src] Issue #24636: 8.6: any user opcode handler for ZEND_FETCH_OBJ_R that returns ZEND_USER_OPCODE_DISPATCH crashes when the operand is $this
| From: | h4acda | Date: | Sat, 24 Oct 2026 08:45:03 +0000 |
| Subject: | [php-src] Issue #24636: 8.6: any user opcode handler for ZEND_FETCH_OBJ_R that returns ZEND_USER_OPCODE_DISPATCH crashes when the operand is $this | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-253152@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/24636
Author: h4acda
### Description
Summary
On PHP 8.6.0beta3, installing any user opcode handler for ZEND_FETCH_OBJ_R whose body is only return
ZEND_USER_OPCODE_DISPATCH; kills the process with SIGBUS when the fetched operand is $this inside a
method. The handler does nothing — it hands the opcode straight back to the engine. The same
extension does not crash on 8.3.33 or 8.5.12.
Environment
- PHP 8.6.0beta3 (cli), macOS aarch64, MacPorts build
- Checked against 8.3.33 and 8.5.12 (same extension, same script): both print x and exit 0
- Extension built with phpize against each runtime
Reproduction
Minimal extension (fetch_min.c, config.m4 attached) — the handler body is a pure pass-through:
static int fetch_min_handler(zend_execute_data *execute_data)
{
return ZEND_USER_OPCODE_DISPATCH;
}
PHP_MINIT_FUNCTION(fetch_min)
{
zend_set_user_opcode_handler(ZEND_FETCH_OBJ_R, fetch_min_handler);
return SUCCESS;
}
phpize && ./configure --enable-fetch-min && make
php -d extension=modules/fetch_min.so repro.php
repro.php:
class A {
public $v = 'x';
function plain() {
return $this->v;
}
}
echo (new A)->plain(), "\n";
Actual result
On 8.6.0beta3 the script prints nothing and the process dies with SIGBUS
(EXC_BAD_ACCESS, KERN_PROTECTION_FAILURE).
macOS crash reporter captured two distinct fault points with this extension
during the session (reports attached):
1. During exception unwind:
cleanup_unfinished_calls.cold.1
cleanup_unfinished_calls
ZEND_HANDLE_EXCEPTION_SPEC_TAILCALL_HANDLER
execute_ex
zend_execute
zend_execute_script
php_execute_script_ex
do_cli
1. Directly inside the opcode handler itself, with the faulting frame being
ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER.
Expected result
The pass-through handler should be transparent: the script should print x
and exit 0, as it does on 8.3.33 and 8.5.12.
Additional notes
Found while prototyping an extension-methods syntax probe (compile-time
source transform plus opcode hooks). The pass-through handler was the minimal
delta I reduced to that still crashes — nothing in the handler touches the
operand, so the fault is in how the engine re-enters or later unwinds a frame
whose FETCH_OBJ_R was intercepted with an UNUSED ($this) operand.
### PHP Version
```plain
php86-scalars
https://api.github.com/repos/hollyschilling/php-src/branches/extension-methods-scalars
```
### Operating System
_No response_