diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 4cefbd58fc7..491d68714b3 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1996,9 +1996,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 e13a38d1676..3e0b9ee3724 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -730,7 +730,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); } }