Skip to content

Instantly share code, notes, and snippets.

@dstogov
Last active April 22, 2024 17:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dstogov/85cb15ff3d3c6c38e57d6a989b5f6261 to your computer and use it in GitHub Desktop.
Save dstogov/85cb15ff3d3c6c38e57d6a989b5f6261 to your computer and use it in GitHub Desktop.
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index 491d68714b3..155156478bf 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -1139,6 +1139,13 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
}
if (!check_only && (parent_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_CHANGED))) {
+ if (child_scope != ce && child->type == ZEND_USER_FUNCTION && child_zv) {
+ /* op_array wasn't duplicated yet */
+ zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
+ memcpy(new_function, child, sizeof(zend_op_array));
+ Z_PTR_P(child_zv) = child = new_function;
+ child_zv = NULL;
+ }
child->common.fn_flags |= ZEND_ACC_CHANGED;
}
@@ -1154,13 +1161,13 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
parent = proto;
}
- if (!check_only && child->common.prototype != proto && child_zv) {
+ if (!check_only && child->common.prototype != proto) {
do {
- if (child->common.scope != ce && child->type == ZEND_USER_FUNCTION) {
+ if (child_scope != ce && child->type == ZEND_USER_FUNCTION) {
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
/* Few parent interfaces contain the same method */
break;
- } else {
+ } else if (child_zv) {
/* op_array wasn't duplicated yet */
zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
memcpy(new_function, child, sizeof(zend_op_array));
@@ -1948,11 +1955,13 @@ static zend_class_entry *fixup_trait_scope(const zend_function *fn, zend_class_e
static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_string *key, zend_function *fn) /* {{{ */
{
+ zval *existing_zv = zend_hash_find(&ce->function_table, key);
zend_function *existing_fn = NULL;
zend_function *new_fn;
bool check_inheritance = false;
- if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) {
+ if (existing_zv != NULL) {
+ existing_fn = Z_PTR_P(existing_zv);
/* if it is the same function with the same visibility and has not been assigned a class scope yet, regardless
* of where it is coming from there is no conflict and we do not need to add it again */
if (existing_fn->op_array.opcodes == fn->op_array.opcodes &&
@@ -1970,7 +1979,7 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
*/
do_inheritance_check_on_method(
existing_fn, fixup_trait_scope(existing_fn, ce), fn, fixup_trait_scope(fn, ce),
- ce, NULL, /* check_visibility */ 0);
+ ce, existing_zv, /* check_visibility */ 0);
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment