From 7384d6fc0d6ae2f6e93fb2ca7e8646aa1da6ab5b Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sun, 17 Mar 2024 01:43:33 +0100 Subject: [PATCH] Fix GH-13712: Segmentation fault for enabled observers when calling trait method of internal trait when opcache is loaded Inherited methods regardless of source must share the original runtime cache. Traits were missed. This adds ZEND_ACC_TRAIT_CLONE to internal functions as well to allow easy distinction of these. On top of that, also fixing the minimum base of the shared opcache memory to the second huge page to avoid a possible 0x0 base, which may cause all sorts of segfaults. (Breaks WSL 1.) --- NEWS | 2 ++ Zend/zend_inheritance.c | 2 +- ext/opcache/tests/gh13712.phpt | 23 +++++++++++++++++++++++ ext/opcache/zend_persist.c | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/gh13712.phpt 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); } }