diff --git a/NEWS b/NEWS index cb573df6587..14d9aa5ef6f 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,8 @@ PHP NEWS - Opcache: . Fixed GH-13508 (JITed QM_ASSIGN may be optimized out when op1 is null). (Arnaud, Dmitry) + . Fixed GH-13712 (Segmentation fault for enabled observers when calling trait + method of internal trait when opcache is loaded). (Bob) - Random: . Fixed bug GH-13544 (Pre-PHP 8.2 compatibility for mt_srand with unknown diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index ea8cc219a23..7f05db05b83 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1993,9 +1993,9 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_ } else { new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); memcpy(new_fn, fn, sizeof(zend_op_array)); - new_fn->op_array.fn_flags |= ZEND_ACC_TRAIT_CLONE; new_fn->op_array.fn_flags &= ~ZEND_ACC_IMMUTABLE; } + new_fn->common.fn_flags |= ZEND_ACC_TRAIT_CLONE; /* Reassign method name, in case it is an alias. */ new_fn->common.function_name = name; diff --git a/ext/opcache/tests/gh13712.phpt b/ext/opcache/tests/gh13712.phpt new file mode 100644 index 00000000000..e770375e33e --- /dev/null +++ b/ext/opcache/tests/gh13712.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-13712 (Segmentation fault for enabled observers when calling trait method of internal trait when opcache is loaded) +--EXTENSIONS-- +opcache +zend_test +--INI-- +zend_test.observer.enabled=1 +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- +testMethod()); +?> +--EXPECTF-- + + + +bool(true) diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index b10e5a8046a..5033b90a8ce 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -729,7 +729,7 @@ static void zend_persist_class_method(zval *zv, zend_class_entry *ce) } // Real dynamically created internal functions like enum methods must have their own run_time_cache pointer. They're always on the same scope as their defining class. // However, copies - as caused by inheritance of internal methods - must retain the original run_time_cache pointer, shared with the source function. - if (!op_array->scope || op_array->scope == ce) { + if (!op_array->scope || (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))) { ZEND_MAP_PTR_NEW(op_array->run_time_cache); } }