From b106feae71571b89d112a1a260d90df9c6c2fa9f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 12 Nov 2024 13:41:49 +0300 Subject: [PATCH] Improve zend_jit_may_be_modified() check (#16760) --- ext/opcache/jit/zend_jit.c | 63 +++++++++++++++++++++++++++++ ext/opcache/jit/zend_jit_internal.h | 20 --------- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index da3dacf338d57..40ca50d970a89 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -692,6 +692,69 @@ static bool zend_may_be_dynamic_property(zend_class_entry *ce, zend_string *memb return 0; } +static bool zend_jit_class_may_be_modified(const zend_class_entry *ce, const zend_op_array *called_from) +{ + uint32_t i; + + if (ce->type == ZEND_INTERNAL_CLASS) { +#ifdef _WIN32 + /* ASLR */ + return 1; +#else + return 0; +#endif + } else if (ce->type == ZEND_USER_CLASS) { + if (ce->ce_flags & ZEND_ACC_PRELOADED) { + return 0; + } + if (ce->info.user.filename == called_from->filename) { + if (ce->parent && zend_jit_class_may_be_modified(ce->parent, called_from)) { + return 1; + } + if (ce->num_interfaces) { + for (i = 0; i < ce->num_interfaces; i++) { + if (zend_jit_class_may_be_modified(ce->interfaces[i], called_from)) { + return 1; + } + } + } + if (ce->num_traits) { + for (i=0; i < ce->num_traits; i++) { + zend_class_entry *trait = zend_fetch_class_by_name(ce->trait_names[i].name, + ce->trait_names[i].lc_name, ZEND_FETCH_CLASS_TRAIT); + if (zend_jit_class_may_be_modified(trait, called_from)) { + return 1; + } + } + } + return 0; + } + } + return 1; +} + +static bool zend_jit_may_be_modified(const zend_function *func, const zend_op_array *called_from) +{ + if (func->type == ZEND_INTERNAL_FUNCTION) { +#ifdef _WIN32 + /* ASLR */ + return 1; +#else + return 0; +#endif + } else if (func->type == ZEND_USER_FUNCTION) { + if (func->common.fn_flags & ZEND_ACC_PRELOADED) { + return 0; + } + if (func->op_array.filename == called_from->filename + && (!func->op_array.scope + || !zend_jit_class_may_be_modified(func->op_array.scope, called_from))) { + return 0; + } + } + return 1; +} + #define OP_RANGE(ssa_op, opN) \ (((opline->opN##_type & (IS_TMP_VAR|IS_VAR|IS_CV)) && \ ssa->var_info && \ diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 9a09be49f1bd5..61d8a853fa005 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -683,26 +683,6 @@ static zend_always_inline const zend_op* zend_jit_trace_get_exit_opline(zend_jit return NULL; } -static inline bool zend_jit_may_be_modified(const zend_function *func, const zend_op_array *called_from) -{ - if (func->type == ZEND_INTERNAL_FUNCTION) { -#ifdef _WIN32 - /* ASLR */ - return 1; -#else - return 0; -#endif - } else if (func->type == ZEND_USER_FUNCTION) { - if (func->common.fn_flags & ZEND_ACC_PRELOADED) { - return 0; - } - if (func->op_array.filename == called_from->filename && !func->op_array.scope) { - return 0; - } - } - return 1; -} - static zend_always_inline bool zend_jit_may_be_polymorphic_call(const zend_op *opline) { if (opline->opcode == ZEND_INIT_FCALL