From 32c919b474b19c1a0c23510b427cc4c50f8d5347 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 15 Sep 2025 11:30:23 +0200 Subject: [PATCH] Handle references after FETCH_OBJ_R with REG destination zend_jit_fetch_obj_r_slow_ex() may be used by the function JIT, which doesn't rely on guards to handle references. Therefore it must deref the property value. Other variants of zend_jit_fetch_obj_*_slow_ex can not be used used in function JIT. Fixes GH-19831 Closes GH-19838 --- NEWS | 1 + ext/opcache/jit/zend_jit_helpers.c | 9 ++++-- ext/opcache/tests/jit/gh19831_001.phpt | 33 ++++++++++++++++++++++ ext/opcache/tests/jit/gh19831_002.phpt | 39 ++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/jit/gh19831_001.phpt create mode 100644 ext/opcache/tests/jit/gh19831_002.phpt diff --git a/NEWS b/NEWS index d3a0da9d242..be73b28b822 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,7 @@ PHP NEWS - Opcache: . Fixed bug GH-19669 (assertion failure in zend_jit_trace_type_to_info_ex). (Arnaud) + . Fixed bug GH-19831 (function JIT may not deref property value). (Arnaud) - Soap: . Fixed bug GH-19784 (SoapServer memory leak). (nielsdos) diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 0f5e1b11c39..a98b9ebc776 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1965,8 +1965,13 @@ static zval* ZEND_FASTCALL zend_jit_fetch_obj_r_slow_ex(zend_object *zobj) void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS); retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, result); - if (retval == result && UNEXPECTED(Z_ISREF_P(retval))) { - zend_unwrap_reference(retval); + if (UNEXPECTED(Z_ISREF_P(retval))) { + if (retval == result) { + zend_unwrap_reference(retval); + } else { + retval = Z_REFVAL_P(retval); + } + ZEND_ASSERT(!Z_REFCOUNTED_P(retval)); } return retval; } diff --git a/ext/opcache/tests/jit/gh19831_001.phpt b/ext/opcache/tests/jit/gh19831_001.phpt new file mode 100644 index 00000000000..c83ca6daa50 --- /dev/null +++ b/ext/opcache/tests/jit/gh19831_001.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-19831 001: fetch obj slow R REG + reference +--CREDITS-- +dktapps +--ENV-- +RT_COND=1 +--INI-- +opcache.jit=1203 +--FILE-- +layers; + } +} + +$t = new Test(); +$a = &$t->layers; +var_dump($t->getLayers()); + +?> +--EXPECT-- +int(1) diff --git a/ext/opcache/tests/jit/gh19831_002.phpt b/ext/opcache/tests/jit/gh19831_002.phpt new file mode 100644 index 00000000000..25b596a3dec --- /dev/null +++ b/ext/opcache/tests/jit/gh19831_002.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-19831 002: fetch obj slow R REG + __get + reference +--CREDITS-- +dktapps +--ENV-- +RT_COND=1 +--INI-- +opcache.jit=1203 +--FILE-- +layers; + } +} + +$t = new Test(); +unset($t->layers); +var_dump($t->getLayers()); + +?> +--EXPECT-- +int(1)