summaryrefslogtreecommitdiff
path: root/Zend/zend_inheritance.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_inheritance.c')
-rw-r--r--Zend/zend_inheritance.c216
1 files changed, 140 insertions, 76 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index 64e7407f12..44abfb6ffb 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -25,9 +25,9 @@
#include "zend_smart_str.h"
#include "zend_inheritance.h"
-static void ptr_dtor(zval *zv) /* {{{ */
+static void overriden_ptr_dtor(zval *zv) /* {{{ */
{
- efree(Z_PTR_P(zv));
+ efree_size(Z_PTR_P(zv), sizeof(zend_function));
}
/* }}} */
@@ -170,7 +170,7 @@ char *zend_visibility_string(uint32_t fn_flags) /* {{{ */
static int zend_do_perform_type_hint_check(const zend_function *fe, zend_arg_info *fe_arg_info, const zend_function *proto, zend_arg_info *proto_arg_info) /* {{{ */
{
if (ZEND_LOG_XOR(fe_arg_info->class_name, proto_arg_info->class_name)) {
- /* Only one has a type hint and the other one doesn't */
+ /* Only one has a type declaration and the other one doesn't */
return 0;
}
@@ -213,15 +213,11 @@ static int zend_do_perform_type_hint_check(const zend_function *fe, zend_arg_inf
}
if (strcasecmp(ZSTR_VAL(fe_class_name), ZSTR_VAL(proto_class_name)) != 0) {
- const char *colon;
-
if (fe->common.type != ZEND_USER_FUNCTION) {
zend_string_release(proto_class_name);
zend_string_release(fe_class_name);
return 0;
- } else if (strchr(ZSTR_VAL(proto_class_name), '\\') != NULL ||
- (colon = zend_memrchr(ZSTR_VAL(fe_class_name), '\\', ZSTR_LEN(fe_class_name))) == NULL ||
- strcasecmp(colon+1, ZSTR_VAL(proto_class_name)) != 0) {
+ } else {
zend_class_entry *fe_ce, *proto_ce;
fe_ce = zend_lookup_class(fe_class_name);
@@ -243,7 +239,7 @@ static int zend_do_perform_type_hint_check(const zend_function *fe, zend_arg_inf
}
if (fe_arg_info->type_hint != proto_arg_info->type_hint) {
- /* Incompatible type hint */
+ /* Incompatible type */
return 0;
}
@@ -323,6 +319,12 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
return 0;
}
+ // This introduces BC break described at https://bugs.php.net/bug.php?id=72119
+ if (proto_arg_info->type_hint && proto_arg_info->allow_null && !fe_arg_info->allow_null) {
+ /* incompatible nullability */
+ return 0;
+ }
+
/* by-ref constraints on arguments are invariant */
if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) {
return 0;
@@ -340,13 +342,22 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
if (!zend_do_perform_type_hint_check(fe, fe->common.arg_info - 1, proto, proto->common.arg_info - 1)) {
return 0;
}
+
+ if (fe->common.arg_info[-1].allow_null && !proto->common.arg_info[-1].allow_null) {
+ return 0;
+ }
}
return 1;
}
/* }}} */
-static void zend_append_type_hint(smart_str *str, const zend_function *fptr, zend_arg_info *arg_info, int return_hint) /* {{{ */
+static ZEND_COLD void zend_append_type_hint(smart_str *str, const zend_function *fptr, zend_arg_info *arg_info, int return_hint) /* {{{ */
{
+
+ if (arg_info->type_hint != IS_UNDEF && arg_info->allow_null) {
+ smart_str_appendc(str, '?');
+ }
+
if (arg_info->class_name) {
const char *class_name;
size_t class_name_len;
@@ -387,7 +398,7 @@ static void zend_append_type_hint(smart_str *str, const zend_function *fptr, zen
}
/* }}} */
-static zend_string *zend_get_function_declaration(const zend_function *fptr) /* {{{ */
+static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function *fptr) /* {{{ */
{
smart_str str = {0};
@@ -543,17 +554,17 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
}
+ /* Prevent derived classes from restricting access that was available in parent classes */
+ if (UNEXPECTED((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK))) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), ZSTR_VAL(child->common.function_name), zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
+ }
+
+ if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
+ && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
+ child->common.fn_flags |= ZEND_ACC_CHANGED;
+ }
if (parent_flags & ZEND_ACC_CHANGED) {
child->common.fn_flags |= ZEND_ACC_CHANGED;
- } else {
- /* Prevent derived classes from restricting access that was available in parent classes
- */
- if (UNEXPECTED((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), ZSTR_VAL(child->common.function_name), zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
- } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
- && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
- child->common.fn_flags |= ZEND_ACC_CHANGED;
- }
}
if (parent_flags & ZEND_ACC_PRIVATE) {
@@ -567,17 +578,32 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
}
if (child->common.prototype && (
- child->common.prototype->common.fn_flags & (ZEND_ACC_ABSTRACT | ZEND_ACC_HAS_RETURN_TYPE)
+ child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT
)) {
- if (UNEXPECTED(!zend_do_perform_implementation_check(child, child->common.prototype))) {
- zend_string *method_prototype = zend_get_function_declaration(child->common.prototype);
- zend_string *child_prototype = zend_get_function_declaration(child);
- zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype));
- }
- } else if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) {
+ parent = child->common.prototype;
+ }
+ if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) {
+ int error_level;
+ const char *error_verb;
zend_string *method_prototype = zend_get_function_declaration(parent);
zend_string *child_prototype = zend_get_function_declaration(child);
- zend_error(E_WARNING, "Declaration of %s should be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype));
+
+ if (child->common.prototype && (
+ child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT
+ )) {
+ error_level = E_COMPILE_ERROR;
+ error_verb = "must";
+ } else if ((parent->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) &&
+ (!(child->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
+ !zend_do_perform_type_hint_check(child, child->common.arg_info - 1, parent, parent->common.arg_info - 1) ||
+ (child->common.arg_info[-1].allow_null && !parent->common.arg_info[-1].allow_null))) {
+ error_level = E_COMPILE_ERROR;
+ error_verb = "must";
+ } else {
+ error_level = E_WARNING;
+ error_verb = "should";
+ }
+ zend_error(error_level, "Declaration of %s %s be compatible with %s", ZSTR_VAL(child_prototype), error_verb, ZSTR_VAL(method_prototype));
zend_string_free(child_prototype);
zend_string_free(method_prototype);
}
@@ -589,7 +615,20 @@ static zend_function *do_inherit_method(zend_string *key, zend_function *parent,
zval *child = zend_hash_find(&ce->function_table, key);
if (child) {
- do_inheritance_check_on_method((zend_function*)Z_PTR_P(child), parent);
+ zend_function *func = (zend_function*)Z_PTR_P(child);
+ zend_function *orig_prototype = func->common.prototype;
+
+ do_inheritance_check_on_method(func, parent);
+ if (func->common.prototype != orig_prototype &&
+ func->type == ZEND_USER_FUNCTION &&
+ func->common.scope != ce &&
+ !func->op_array.static_variables) {
+ /* Lazy duplication */
+ zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
+ memcpy(new_function, func, sizeof(zend_op_array));
+ Z_PTR_P(child) = new_function;
+ func->common.prototype = orig_prototype;
+ }
return NULL;
}
@@ -627,7 +666,8 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
int parent_num = OBJ_PROP_TO_NUM(parent_info->offset);
int child_num = OBJ_PROP_TO_NUM(child_info->offset);
- zval_ptr_dtor(&(ce->default_properties_table[parent_num]));
+ /* Don't keep default properties in GC (they may be freed by opcache) */
+ zval_ptr_dtor_nogc(&(ce->default_properties_table[parent_num]));
ce->default_properties_table[parent_num] = ce->default_properties_table[child_num];
ZVAL_UNDEF(&ce->default_properties_table[child_num]);
child_info->offset = parent_info->offset;
@@ -702,21 +742,29 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_
}
/* }}} */
-static void do_inherit_class_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
+static void do_inherit_class_constant(zend_string *name, zend_class_constant *parent_const, zend_class_entry *ce) /* {{{ */
{
- if (!zend_hash_exists(&ce->constants_table, name)) {
- if (!Z_ISREF_P(zv)) {
- if (parent_ce->type == ZEND_INTERNAL_CLASS) {
- ZVAL_NEW_PERSISTENT_REF(zv, zv);
- } else {
- ZVAL_NEW_REF(zv, zv);
- }
+ zend_class_constant *c = zend_hash_find_ptr(&ce->constants_table, name);
+
+ if (c != NULL) {
+ if (UNEXPECTED((Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PPP_MASK) > (Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PPP_MASK))) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s must be %s (as in class %s)%s",
+ ZSTR_VAL(ce->name), ZSTR_VAL(name), zend_visibility_string(Z_ACCESS_FLAGS(parent_const->value)), ZSTR_VAL(ce->parent->name), (Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PUBLIC) ? "" : " or weaker");
}
- if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
+ } else if (!(Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PRIVATE)) {
+ if (Z_CONSTANT(parent_const->value)) {
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
}
- Z_ADDREF_P(zv);
- _zend_hash_append(&ce->constants_table, name, zv);
+ if (ce->type & ZEND_INTERNAL_CLASS) {
+ if (Z_REFCOUNTED(parent_const->value)) {
+ Z_ADDREF(parent_const->value);
+ }
+ c = pemalloc(sizeof(zend_class_constant), 1);
+ memcpy(c, parent_const, sizeof(zend_class_constant));
+ } else {
+ c = parent_const;
+ }
+ _zend_hash_append_ptr(&ce->constants_table, name, c);
}
}
/* }}} */
@@ -726,7 +774,6 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
zend_property_info *property_info;
zend_function *func;
zend_string *key;
- zval *zv;
if (UNEXPECTED(ce->ce_flags & ZEND_ACC_INTERFACE)) {
/* Interface can only inherit other interfaces */
@@ -821,7 +868,13 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
do {
dst--;
src--;
- ZVAL_MAKE_REF(src);
+ if (parent_ce->type == ZEND_INTERNAL_CLASS) {
+ if (!Z_ISREF_P(src)) {
+ ZVAL_NEW_PERSISTENT_REF(src, src);
+ }
+ } else {
+ ZVAL_MAKE_REF(src);
+ }
ZVAL_COPY_VALUE(dst, src);
Z_ADDREF_P(dst);
if (Z_CONSTANT_P(Z_REFVAL_P(dst))) {
@@ -831,6 +884,8 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
ce->default_static_members_count += parent_ce->default_static_members_count;
if (ce->type == ZEND_USER_CLASS) {
ce->static_members_table = ce->default_static_members_table;
+ } else {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
}
}
@@ -855,12 +910,14 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
}
if (zend_hash_num_elements(&parent_ce->constants_table)) {
+ zend_class_constant *c;
+
zend_hash_extend(&ce->constants_table,
zend_hash_num_elements(&ce->constants_table) +
zend_hash_num_elements(&parent_ce->constants_table), 0);
- ZEND_HASH_FOREACH_STR_KEY_VAL(&parent_ce->constants_table, key, zv) {
- do_inherit_class_constant(key, zv, ce, parent_ce);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->constants_table, key, c) {
+ do_inherit_class_constant(key, c, ce);
} ZEND_HASH_FOREACH_END();
}
@@ -890,14 +947,12 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
}
/* }}} */
-static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zval *parent_constant, zend_string *name, const zend_class_entry *iface) /* {{{ */
+static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zend_class_constant *parent_constant, zend_string *name, const zend_class_entry *iface) /* {{{ */
{
- zval *old_constant;
+ zend_class_constant *old_constant;
- if ((old_constant = zend_hash_find(child_constants_table, name)) != NULL) {
- if (!Z_ISREF_P(old_constant) ||
- !Z_ISREF_P(parent_constant) ||
- Z_REFVAL_P(old_constant) != Z_REFVAL_P(parent_constant)) {
+ if ((old_constant = zend_hash_find_ptr(child_constants_table, name)) != NULL) {
+ if (old_constant->ce != parent_constant->ce) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", ZSTR_VAL(name), ZSTR_VAL(iface->name));
}
return 0;
@@ -906,15 +961,23 @@ static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zva
}
/* }}} */
-static void do_inherit_iface_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
+static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
{
- if (do_inherit_constant_check(&ce->constants_table, zv, name, iface)) {
- ZVAL_MAKE_REF(zv);
- Z_ADDREF_P(zv);
- if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
+ if (do_inherit_constant_check(&ce->constants_table, c, name, iface)) {
+ zend_class_constant *ct;
+ if (Z_CONSTANT(c->value)) {
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
}
- zend_hash_update(&ce->constants_table, name, zv);
+ if (ce->type & ZEND_INTERNAL_CLASS) {
+ if (Z_REFCOUNTED(c->value)) {
+ Z_ADDREF(c->value);
+ }
+ ct = pemalloc(sizeof(zend_class_constant), 1);
+ memcpy(ct, c, sizeof(zend_class_constant));
+ } else {
+ ct = c;
+ }
+ zend_hash_update_ptr(&ce->constants_table, name, ct);
}
}
/* }}} */
@@ -926,7 +989,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
uint32_t parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0;
zend_function *func;
zend_string *key;
- zval *zv;
+ zend_class_constant *c;
for (i = 0; i < ce->num_interfaces; i++) {
if (ce->interfaces[i] == NULL) {
@@ -942,8 +1005,8 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
}
if (ignore) {
/* Check for attempt to redeclare interface constants */
- ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, zv) {
- do_inherit_constant_check(&iface->constants_table, zv, key, iface);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
+ do_inherit_constant_check(&iface->constants_table, c, key, iface);
} ZEND_HASH_FOREACH_END();
} else {
if (ce->num_interfaces >= current_iface_num) {
@@ -955,8 +1018,8 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
}
ce->interfaces[ce->num_interfaces++] = iface;
- ZEND_HASH_FOREACH_STR_KEY_VAL(&iface->constants_table, key, zv) {
- do_inherit_iface_constant(key, zv, ce, iface);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
+ do_inherit_iface_constant(key, c, ce, iface);
} ZEND_HASH_FOREACH_END();
ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) {
@@ -1016,34 +1079,34 @@ static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_
static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zend_function* fe) /* {{{ */
{
- if (!strncmp(ZSTR_VAL(mname), ZEND_CLONE_FUNC_NAME, ZSTR_LEN(mname))) {
+ if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) {
ce->clone = fe; fe->common.fn_flags |= ZEND_ACC_CLONE;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_CONSTRUCTOR_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
}
ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_DESTRUCTOR_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_DESTRUCTOR_FUNC_NAME)) {
ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_GET_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_GET_FUNC_NAME)) {
ce->__get = fe;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_SET_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_SET_FUNC_NAME)) {
ce->__set = fe;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_CALL_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_CALL_FUNC_NAME)) {
ce->__call = fe;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_UNSET_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_UNSET_FUNC_NAME)) {
ce->__unset = fe;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_ISSET_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_ISSET_FUNC_NAME)) {
ce->__isset = fe;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_CALLSTATIC_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_CALLSTATIC_FUNC_NAME)) {
ce->__callstatic = fe;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_TOSTRING_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_TOSTRING_FUNC_NAME)) {
ce->__tostring = fe;
- } else if (!strncmp(ZSTR_VAL(mname), ZEND_DEBUGINFO_FUNC_NAME, ZSTR_LEN(mname))) {
+ } else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) {
ce->__debugInfo = fe;
} else if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) {
zend_string *lowercase_name = zend_string_tolower(ce->name);
@@ -1090,7 +1153,7 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s
}
} else {
ALLOC_HASHTABLE(*overriden);
- zend_hash_init_ex(*overriden, 8, NULL, ptr_dtor, 0, 0);
+ zend_hash_init_ex(*overriden, 8, NULL, overriden_ptr_dtor, 0, 0);
}
zend_hash_update_mem(*overriden, key, fn, sizeof(zend_function));
return;
@@ -1192,7 +1255,8 @@ static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, ze
if (exclude_table == NULL || zend_hash_find(exclude_table, fnname) == NULL) {
/* is not in hashtable, thus, function is not to be excluded */
- fn_copy = *fn;
+ /* And how about ZEND_OVERLOADED_FUNCTION? */
+ memcpy(&fn_copy, fn, fn->type == ZEND_USER_FUNCTION? sizeof(zend_op_array) : sizeof(zend_internal_function));
/* apply aliases which have not alias name, just setting visibility */
if (ce->trait_aliases) {