diff --git a/NEWS b/NEWS index 7c1ccee1c9862..8afb4a4c82506 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,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) - PDO: . Fix various PDORow bugs. (Girgias) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index b34823569fc1c..cec0ffdb1853b 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1917,9 +1917,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 0000000000000..e770375e33e46 --- /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 149bcb730bee1..87f1aee1480bc 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -726,7 +726,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); } }