From 1e78cf941c842987a363361915072013a9eb306e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 2 Sep 2024 21:55:19 +0300 Subject: [PATCH] Fix GH-15652: Segmentation fault in the Zend engine when JIT enabled (#15717) --- ext/opcache/jit/zend_jit.c | 6 ++-- ext/opcache/jit/zend_jit_arm64.dasc | 2 +- ext/opcache/jit/zend_jit_x86.dasc | 2 +- ext/opcache/tests/jit/gh15652.phpt | 46 +++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 ext/opcache/tests/jit/gh15652.phpt diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index ce091509785..39d3145275c 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -669,16 +669,16 @@ static zend_property_info* zend_get_known_property_info(const zend_op_array *op_ return NULL; } -static bool zend_may_be_dynamic_property(zend_class_entry *ce, zend_string *member, bool on_this, zend_string *filename) +static bool zend_may_be_dynamic_property(zend_class_entry *ce, zend_string *member, bool on_this, const zend_op_array *op_array) { zend_property_info *info; - if (!ce || (ce->ce_flags & ZEND_ACC_TRAIT)) { + if (!ce || (ce->ce_flags & ZEND_ACC_TRAIT) || (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { return 1; } if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) { - if (ce->info.user.filename != filename) { + if (ce->info.user.filename != op_array->filename) { /* class declaration might be changed independently */ return 1; } diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index f6b34e3baf3..05219b3cfae 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -12200,7 +12200,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, | cmp REG2, TMP1 | bne >5 | MEM_ACCESS_64_WITH_UOFFSET ldr, REG0, REG0, ((opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) + sizeof(void*)), TMP1 - may_be_dynamic = zend_may_be_dynamic_property(ce, Z_STR_P(member), opline->op1_type == IS_UNUSED, op_array->filename); + may_be_dynamic = zend_may_be_dynamic_property(ce, Z_STR_P(member), opline->op1_type == IS_UNUSED, op_array); if (may_be_dynamic) { | tst REG0, REG0 if (opline->opcode == ZEND_FETCH_OBJ_W) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 7b28b2a767a..999295ef01a 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -12964,7 +12964,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, | cmp r2, aword [FCARG1a + offsetof(zend_object, ce)] | jne >5 | mov r0, aword [r0 + (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) + sizeof(void*)] - may_be_dynamic = zend_may_be_dynamic_property(ce, Z_STR_P(member), opline->op1_type == IS_UNUSED, op_array->filename); + may_be_dynamic = zend_may_be_dynamic_property(ce, Z_STR_P(member), opline->op1_type == IS_UNUSED, op_array); if (may_be_dynamic) { | test r0, r0 if (opline->opcode == ZEND_FETCH_OBJ_W) { diff --git a/ext/opcache/tests/jit/gh15652.phpt b/ext/opcache/tests/jit/gh15652.phpt new file mode 100644 index 00000000000..2220c7550a6 --- /dev/null +++ b/ext/opcache/tests/jit/gh15652.phpt @@ -0,0 +1,46 @@ +--TEST-- +JIT: FETCH_OBJ 007 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.jit_hot_func=2 +--FILE-- +value === $type->value; + } +} + +class C1 extends C { + use T; + public function __construct(private int $value) {} +} + +class C2 extends C { + use T; +} + +$x = new C1(1); +var_dump($x->equal($x)); +var_dump($x->equal($x)); +$a = new C2("aaa"); +var_dump($a->equal($a)); +var_dump($a->equal($a)); +--EXPECTF-- +bool(true) +bool(true) + +Warning: Undefined property: C2::$value in %sgh15652.php on line 6 + +Warning: Undefined property: C2::$value in %sgh15652.php on line 6 +bool(true) + +Warning: Undefined property: C2::$value in %sgh15652.php on line 6 + +Warning: Undefined property: C2::$value in %sgh15652.php on line 6 +bool(true) \ No newline at end of file