From b30448f48f6f1d84b15d3b2ace18933c9a206061 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Wed, 2 Nov 2022 15:28:53 +0100 Subject: [PATCH] Fix observing inherited internal functions Fixes GH-9871 --- Zend/zend_inheritance.c | 5 ++--- ext/opcache/zend_persist.c | 6 +++++- ext/zend_test/tests/gh9871.phpt | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 ext/zend_test/tests/gh9871.phpt diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 3eaaca3409a..2d997097578 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -3135,13 +3135,11 @@ static zend_always_inline bool register_early_bound_ce(zval *delayed_early_bindi if (EXPECTED(!(ce->ce_flags & ZEND_ACC_PRELOADED))) { if (zend_hash_set_bucket_key(EG(class_table), (Bucket *)delayed_early_binding, lcname) != NULL) { Z_CE_P(delayed_early_binding) = ce; - zend_observer_class_linked_notify(ce, lcname); return true; } } else { /* If preloading is used, don't replace the existing bucket, add a new one. */ if (zend_hash_add_ptr(EG(class_table), lcname, ce) != NULL) { - zend_observer_class_linked_notify(ce, lcname); return true; } } @@ -3149,7 +3147,6 @@ static zend_always_inline bool register_early_bound_ce(zval *delayed_early_bindi return false; } if (zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL) { - zend_observer_class_linked_notify(ce, lcname); return true; } return false; @@ -3170,6 +3167,7 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_ if (UNEXPECTED(!register_early_bound_ce(delayed_early_binding, lcname, ret))) { return NULL; } + zend_observer_class_linked_notify(ret, lcname); return ret; } } else { @@ -3244,6 +3242,7 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_ if (ZSTR_HAS_CE_CACHE(ce->name)) { ZSTR_SET_CE_CACHE(ce->name, ce); } + zend_observer_class_linked_notify(ce, lcname); return ce; } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 91765676b38..dcff7a78832 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -723,7 +723,11 @@ static void zend_persist_class_method(zval *zv, zend_class_entry *ce) } } } - ZEND_MAP_PTR_NEW(op_array->run_time_cache); + // 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) { + ZEND_MAP_PTR_NEW(op_array->run_time_cache); + } } } return; diff --git a/ext/zend_test/tests/gh9871.phpt b/ext/zend_test/tests/gh9871.phpt new file mode 100644 index 00000000000..c2b6f359bd6 --- /dev/null +++ b/ext/zend_test/tests/gh9871.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test observing inherited internal functions +--EXTENSIONS-- +zend_test +--INI-- +opcache.enable_cli=1 +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_return_value=1 +--FILE-- +setAccessible(true); + +?> +--EXPECT-- + + + + + + + + +