From f724216cf5ffd6bee7687fdeabb0922863187627 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 9 Sep 2024 23:18:46 +0200 Subject: [PATCH] Fix GH-15657: Segmentation fault in ext/opcache/jit/ir/dynasm/dasm_x86.h The crash happens because the zend_persist.c code tries to JIT the hook's op_array while the JIT buffer memory is still protected. This happens in `zend_persist_property_info` called via `zend_persist_class_entry` through the inheritance cache. We shouldn't JIT the property hook code when persisting property info for the inheritance cache. This is a simple workaround by temporarily disabling the JIT so that the property hook code is not JITted when persisting the property info. An alternative solution would be to move the JITting of the property hooks to a different place in zend_persist.c by doing an additional pass over the classes. --- ext/opcache/ZendAccelerator.c | 13 +++++++++++++ ext/opcache/tests/jit/gh15657.phpt | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 ext/opcache/tests/jit/gh15657.phpt diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index f9514d4807c4..a81dbee97ee5 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2428,9 +2428,22 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce, } ZEND_HASH_FOREACH_END(); ZCG(mem) = (char*)ZCG(mem) + zend_hash_num_elements(dependencies) * sizeof(zend_class_dependency); } + + /* See GH-15657: `zend_persist_class_entry` can JIT property hook code via + * `zend_persist_property_info`, but the inheritance cache should not + * JIT those at this point in time. */ +#ifdef HAVE_JIT + bool jit_on_old = JIT_G(on); + JIT_G(on) = false; +#endif + entry->ce = new_ce = zend_persist_class_entry(ce); zend_update_parent_ce(new_ce); +#ifdef HAVE_JIT + JIT_G(on) = jit_on_old; +#endif + entry->num_warnings = EG(num_errors); entry->warnings = zend_persist_warnings(EG(num_errors), EG(errors)); entry->next = proto->inheritance_cache; diff --git a/ext/opcache/tests/jit/gh15657.phpt b/ext/opcache/tests/jit/gh15657.phpt new file mode 100644 index 000000000000..4fc35d3b5bd0 --- /dev/null +++ b/ext/opcache/tests/jit/gh15657.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-15657 (Segmentation fault in ext/opcache/jit/ir/dynasm/dasm_x86.h) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit_buffer_size=64M +opcache.jit=1101 +--FILE-- + $this->_prop; + } +} +echo "Done\n"; +?> +--EXPECT-- +Done