diff options
-rw-r--r-- | Zend/zend.h | 11 | ||||
-rw-r--r-- | Zend/zend_compile.c | 39 | ||||
-rw-r--r-- | Zend/zend_inheritance.c | 258 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 33 | ||||
-rw-r--r-- | ext/opcache/zend_accelerator_util_funcs.c | 26 | ||||
-rw-r--r-- | ext/opcache/zend_file_cache.c | 97 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 38 | ||||
-rw-r--r-- | ext/opcache/zend_persist_calc.c | 33 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 6 |
9 files changed, 211 insertions, 330 deletions
diff --git a/Zend/zend.h b/Zend/zend.h index b1c1e66867..4a4e38d9c2 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -86,20 +86,17 @@ typedef struct _zend_unserialize_data zend_unserialize_data; typedef struct _zend_trait_method_reference { zend_string *method_name; - zend_class_entry *ce; zend_string *class_name; } zend_trait_method_reference; typedef struct _zend_trait_precedence { - zend_trait_method_reference *trait_method; - union { - zend_class_entry *ce; - zend_string *class_name; - } *exclude_from_classes; + zend_trait_method_reference trait_method; + uint32_t num_excludes; + zend_string *exclude_class_names[1]; } zend_trait_precedence; typedef struct _zend_trait_alias { - zend_trait_method_reference *trait_method; + zend_trait_method_reference trait_method; /** * name for method to be added diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 3eece7687c..afb5f6ea17 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6174,13 +6174,11 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ } /* }}} */ -static zend_trait_method_reference *zend_compile_method_ref(zend_ast *ast) /* {{{ */ +static void zend_compile_method_ref(zend_ast *ast, zend_trait_method_reference *method_ref) /* {{{ */ { zend_ast *class_ast = ast->child[0]; zend_ast *method_ast = ast->child[1]; - zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference)); - method_ref->ce = NULL; method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast)); if (class_ast) { @@ -6188,25 +6186,6 @@ static zend_trait_method_reference *zend_compile_method_ref(zend_ast *ast) /* {{ } else { method_ref->class_name = NULL; } - - return method_ref; -} -/* }}} */ - -static zend_string **zend_compile_name_list(zend_ast *ast) /* {{{ */ -{ - zend_ast_list *list = zend_ast_get_list(ast); - zend_string **names = safe_emalloc(sizeof(zend_string *), list->children + 1, 0); - uint32_t i; - - for (i = 0; i < list->children; ++i) { - zend_ast *name_ast = list->child[i]; - names[i] = zend_resolve_class_name_ast(name_ast); - } - - names[list->children] = NULL; - - return names; } /* }}} */ @@ -6214,11 +6193,17 @@ static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */ { zend_ast *method_ref_ast = ast->child[0]; zend_ast *insteadof_ast = ast->child[1]; + zend_ast_list *insteadof_list = zend_ast_get_list(insteadof_ast); + uint32_t i; + + zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence) + (insteadof_list->children - 1) * sizeof(zend_string*)); + zend_compile_method_ref(method_ref_ast, &precedence->trait_method); + precedence->num_excludes = insteadof_list->children; - zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence)); - precedence->trait_method = zend_compile_method_ref(method_ref_ast); - precedence->exclude_from_classes - = (void *) zend_compile_name_list(insteadof_ast); + for (i = 0; i < insteadof_list->children; ++i) { + zend_ast *name_ast = insteadof_list->child[i]; + precedence->exclude_class_names[i] = zend_resolve_class_name_ast(name_ast); + } zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence); } @@ -6241,7 +6226,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ } alias = emalloc(sizeof(zend_trait_alias)); - alias->trait_method = zend_compile_method_ref(method_ref_ast); + zend_compile_method_ref(method_ref_ast, &alias->trait_method); alias->modifiers = modifiers; if (alias_ast) { diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index c64cb00318..9d7fb939d6 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1257,22 +1257,24 @@ static void zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce) /* } /* }}} */ -static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, zend_class_entry *ce, HashTable **overriden, HashTable *exclude_table) /* {{{ */ +static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, zend_class_entry *ce, HashTable **overriden, HashTable *exclude_table, zend_class_entry **aliases) /* {{{ */ { zend_trait_alias *alias, **alias_ptr; zend_string *lcname; zend_function fn_copy; + int i; /* apply aliases which are qualified with a class name, there should not be any ambiguity */ if (ce->trait_aliases) { alias_ptr = ce->trait_aliases; alias = *alias_ptr; + i = 0; while (alias) { /* Scope unset or equal to the function we compare to, and the alias applies to fn */ if (alias->alias != NULL - && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce) - && ZSTR_LEN(alias->trait_method->method_name) == ZSTR_LEN(fnname) - && (zend_binary_strcasecmp(ZSTR_VAL(alias->trait_method->method_name), ZSTR_LEN(alias->trait_method->method_name), ZSTR_VAL(fnname), ZSTR_LEN(fnname)) == 0)) { + && (!aliases[i] || fn->common.scope == aliases[i]) + && ZSTR_LEN(alias->trait_method.method_name) == ZSTR_LEN(fnname) + && (zend_binary_strcasecmp(ZSTR_VAL(alias->trait_method.method_name), ZSTR_LEN(alias->trait_method.method_name), ZSTR_VAL(fnname), ZSTR_LEN(fnname)) == 0)) { fn_copy = *fn; /* if it is 0, no modifieres has been changed */ @@ -1285,12 +1287,17 @@ static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, ze zend_string_release_ex(lcname, 0); /* Record the trait from which this alias was resolved. */ - if (!alias->trait_method->ce) { - alias->trait_method->ce = fn->common.scope; + if (!aliases[i]) { + aliases[i] = fn->common.scope; + } + if (!alias->trait_method.class_name) { + /* TODO: try to avoid this assignment (it's necessary only for reflection) */ + alias->trait_method.class_name = zend_string_copy(fn->common.scope->name); } } alias_ptr++; alias = *alias_ptr; + i++; } } @@ -1303,22 +1310,28 @@ static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, ze if (ce->trait_aliases) { alias_ptr = ce->trait_aliases; alias = *alias_ptr; + i = 0; while (alias) { /* Scope unset or equal to the function we compare to, and the alias applies to fn */ if (alias->alias == NULL && alias->modifiers != 0 - && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce) - && (ZSTR_LEN(alias->trait_method->method_name) == ZSTR_LEN(fnname)) - && (zend_binary_strcasecmp(ZSTR_VAL(alias->trait_method->method_name), ZSTR_LEN(alias->trait_method->method_name), ZSTR_VAL(fnname), ZSTR_LEN(fnname)) == 0)) { + && (!aliases[i] || fn->common.scope == aliases[i]) + && (ZSTR_LEN(alias->trait_method.method_name) == ZSTR_LEN(fnname)) + && (zend_binary_strcasecmp(ZSTR_VAL(alias->trait_method.method_name), ZSTR_LEN(alias->trait_method.method_name), ZSTR_VAL(fnname), ZSTR_LEN(fnname)) == 0)) { fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK)); /** Record the trait from which this alias was resolved. */ - if (!alias->trait_method->ce) { - alias->trait_method->ce = fn->common.scope; + if (!aliases[i]) { + aliases[i] = fn->common.scope; + } + if (!alias->trait_method.class_name) { + /* TODO: try to avoid this assignment (it's necessary only for reflection) */ + alias->trait_method.class_name = zend_string_copy(fn->common.scope->name); } } alias_ptr++; alias = *alias_ptr; + i++; } } @@ -1329,24 +1342,26 @@ static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, ze } /* }}} */ -static void zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait) /* {{{ */ +static uint32_t zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait) /* {{{ */ { uint32_t i; if (UNEXPECTED((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT)) { zend_error_noreturn(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", ZSTR_VAL(trait->name)); + return 0; } for (i = 0; i < ce->num_traits; i++) { if (ce->traits[i] == trait) { - return; + return i; } } zend_error_noreturn(E_COMPILE_ERROR, "Required Trait %s wasn't added to %s", ZSTR_VAL(trait->name), ZSTR_VAL(ce->name)); + return 0; } /* }}} */ -static void zend_traits_init_trait_structures(zend_class_entry *ce) /* {{{ */ +static void zend_traits_init_trait_structures(zend_class_entry *ce, HashTable ***exclude_tables_ptr, zend_class_entry ***aliases_ptr) /* {{{ */ { size_t i, j = 0; zend_trait_precedence **precedences; @@ -1354,64 +1369,72 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce) /* {{{ */ zend_trait_method_reference *cur_method_ref; zend_string *lcname; zend_bool method_exists; + HashTable **exclude_tables = NULL; + zend_class_entry **aliases = NULL; + zend_class_entry *trait; /* resolve class references */ if (ce->trait_precedences) { + exclude_tables = ecalloc(ce->num_traits, sizeof(HashTable*)); i = 0; precedences = ce->trait_precedences; ce->trait_precedences = NULL; while ((cur_precedence = precedences[i])) { /** Resolve classes for all precedence operations. */ - if (cur_precedence->exclude_from_classes) { - cur_method_ref = cur_precedence->trait_method; - if (!(cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name, - ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD))) { - zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name)); - } - zend_check_trait_usage(ce, cur_precedence->trait_method->ce); + cur_method_ref = &cur_precedence->trait_method; + trait = zend_fetch_class(cur_method_ref->class_name, + ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (!trait) { + zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name)); + } + zend_check_trait_usage(ce, trait); + + /** Ensure that the preferred method is actually available. */ + lcname = zend_string_tolower(cur_method_ref->method_name); + method_exists = zend_hash_exists(&trait->function_table, lcname); + if (!method_exists) { + zend_error_noreturn(E_COMPILE_ERROR, + "A precedence rule was defined for %s::%s but this method does not exist", + ZSTR_VAL(trait->name), + ZSTR_VAL(cur_method_ref->method_name)); + } - /** Ensure that the preferred method is actually available. */ - lcname = zend_string_tolower(cur_method_ref->method_name); - method_exists = zend_hash_exists(&cur_method_ref->ce->function_table, - lcname); - zend_string_release_ex(lcname, 0); - if (!method_exists) { - zend_error_noreturn(E_COMPILE_ERROR, - "A precedence rule was defined for %s::%s but this method does not exist", - ZSTR_VAL(cur_method_ref->ce->name), - ZSTR_VAL(cur_method_ref->method_name)); - } + /** With the other traits, we are more permissive. + We do not give errors for those. This allows to be more + defensive in such definitions. + However, we want to make sure that the insteadof declaration + is consistent in itself. + */ - /** With the other traits, we are more permissive. - We do not give errors for those. This allows to be more - defensive in such definitions. - However, we want to make sure that the insteadof declaration - is consistent in itself. - */ - j = 0; - while (cur_precedence->exclude_from_classes[j].class_name) { - zend_string* class_name = cur_precedence->exclude_from_classes[j].class_name; - - if (!(cur_precedence->exclude_from_classes[j].ce = zend_fetch_class(class_name, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD))) { - zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(class_name)); - } - zend_check_trait_usage(ce, cur_precedence->exclude_from_classes[j].ce); + for (j = 0; j < cur_precedence->num_excludes; j++) { + zend_string* class_name = cur_precedence->exclude_class_names[j]; + zend_class_entry *exclude_ce = zend_fetch_class(class_name, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD); + uint32_t trait_num; - /* make sure that the trait method is not from a class mentioned in - exclude_from_classes, for consistency */ - if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[j].ce) { - zend_error_noreturn(E_COMPILE_ERROR, - "Inconsistent insteadof definition. " - "The method %s is to be used from %s, but %s is also on the exclude list", - ZSTR_VAL(cur_method_ref->method_name), - ZSTR_VAL(cur_precedence->trait_method->ce->name), - ZSTR_VAL(cur_precedence->trait_method->ce->name)); - } + if (!exclude_ce) { + zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(class_name)); + } + trait_num = zend_check_trait_usage(ce, exclude_ce); + if (!exclude_tables[trait_num]) { + ALLOC_HASHTABLE(exclude_tables[trait_num]); + zend_hash_init(exclude_tables[trait_num], 0, NULL, NULL, 0); + } + if (zend_hash_add_empty_element(exclude_tables[trait_num], lcname) == NULL) { + zend_error_noreturn(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", ZSTR_VAL(precedences[i]->trait_method.method_name), ZSTR_VAL(exclude_ce->name)); + } - zend_string_release_ex(class_name, 0); - j++; + /* make sure that the trait method is not from a class mentioned in + exclude_from_classes, for consistency */ + if (trait == exclude_ce) { + zend_error_noreturn(E_COMPILE_ERROR, + "Inconsistent insteadof definition. " + "The method %s is to be used from %s, but %s is also on the exclude list", + ZSTR_VAL(cur_method_ref->method_name), + ZSTR_VAL(trait->name), + ZSTR_VAL(trait->name)); } } + zend_string_release_ex(lcname, 0); i++; } ce->trait_precedences = precedences; @@ -1420,87 +1443,63 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce) /* {{{ */ if (ce->trait_aliases) { i = 0; while (ce->trait_aliases[i]) { + i++; + } + aliases = ecalloc(i, sizeof(zend_class_entry*)); + i = 0; + while (ce->trait_aliases[i]) { /** For all aliases with an explicit class name, resolve the class now. */ - if (ce->trait_aliases[i]->trait_method->class_name) { - cur_method_ref = ce->trait_aliases[i]->trait_method; - if (!(cur_method_ref->ce = zend_fetch_class(cur_method_ref->class_name, ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD))) { + if (ce->trait_aliases[i]->trait_method.class_name) { + cur_method_ref = &ce->trait_aliases[i]->trait_method; + trait = zend_fetch_class(cur_method_ref->class_name, ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (!trait) { zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name)); } - zend_check_trait_usage(ce, cur_method_ref->ce); + zend_check_trait_usage(ce, trait); + aliases[i] = trait; /** And, ensure that the referenced method is resolvable, too. */ lcname = zend_string_tolower(cur_method_ref->method_name); - method_exists = zend_hash_exists(&cur_method_ref->ce->function_table, - lcname); + method_exists = zend_hash_exists(&trait->function_table, lcname); zend_string_release_ex(lcname, 0); if (!method_exists) { - zend_error_noreturn(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", ZSTR_VAL(cur_method_ref->ce->name), ZSTR_VAL(cur_method_ref->method_name)); + zend_error_noreturn(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", ZSTR_VAL(trait->name), ZSTR_VAL(cur_method_ref->method_name)); } } i++; } } -} -/* }}} */ - -static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait) /* {{{ */ -{ - size_t i = 0, j; - if (!precedences) { - return; - } - while (precedences[i]) { - if (precedences[i]->exclude_from_classes) { - j = 0; - while (precedences[i]->exclude_from_classes[j].ce) { - if (precedences[i]->exclude_from_classes[j].ce == trait) { - zend_string *lcname = - zend_string_tolower(precedences[i]->trait_method->method_name); - if (zend_hash_add_empty_element(exclude_table, lcname) == NULL) { - zend_string_release_ex(lcname, 0); - zend_error_noreturn(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", ZSTR_VAL(precedences[i]->trait_method->method_name), ZSTR_VAL(trait->name)); - } - zend_string_release_ex(lcname, 0); - } - ++j; - } - } - ++i; - } + *exclude_tables_ptr = exclude_tables; + *aliases_ptr = aliases; } /* }}} */ -static void zend_do_traits_method_binding(zend_class_entry *ce) /* {{{ */ +static void zend_do_traits_method_binding(zend_class_entry *ce, HashTable **exclude_tables, zend_class_entry **aliases) /* {{{ */ { uint32_t i; HashTable *overriden = NULL; zend_string *key; zend_function *fn; - for (i = 0; i < ce->num_traits; i++) { - if (ce->trait_precedences) { - HashTable exclude_table; - zend_trait_precedence **precedences; - - /* TODO: revisit this start size, may be its not optimal */ - zend_hash_init_ex(&exclude_table, 8, NULL, NULL, 0, 0); - - precedences = ce->trait_precedences; - ce->trait_precedences = NULL; - zend_traits_compile_exclude_table(&exclude_table, precedences, ce->traits[i]); - + if (exclude_tables) { + for (i = 0; i < ce->num_traits; i++) { /* copies functions, applies defined aliasing, and excludes unused trait methods */ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->traits[i]->function_table, key, fn) { - zend_traits_copy_functions(key, fn, ce, &overriden, &exclude_table); + zend_traits_copy_functions(key, fn, ce, &overriden, exclude_tables[i], aliases); } ZEND_HASH_FOREACH_END(); - zend_hash_destroy(&exclude_table); - ce->trait_precedences = precedences; - } else { + if (exclude_tables[i]) { + zend_hash_destroy(exclude_tables[i]); + FREE_HASHTABLE(exclude_tables[i]); + exclude_tables[i] = NULL; + } + } + } else { + for (i = 0; i < ce->num_traits; i++) { ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->traits[i]->function_table, key, fn) { - zend_traits_copy_functions(key, fn, ce, &overriden, NULL); + zend_traits_copy_functions(key, fn, ce, &overriden, NULL, aliases); } ZEND_HASH_FOREACH_END(); } } @@ -1509,17 +1508,6 @@ static void zend_do_traits_method_binding(zend_class_entry *ce) /* {{{ */ zend_fixup_trait_method(fn, ce); } ZEND_HASH_FOREACH_END(); - if (ce->trait_precedences) { - i = 0; - while (ce->trait_precedences[i]) { - if (ce->trait_precedences[i]->exclude_from_classes) { - efree(ce->trait_precedences[i]->exclude_from_classes); - ce->trait_precedences[i]->exclude_from_classes = NULL; - } - i++; - } - } - if (overriden) { zend_hash_destroy(overriden); FREE_HASHTABLE(overriden); @@ -1661,7 +1649,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce) /* {{{ */ } /* }}} */ -static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce) /* {{{ */ +static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce, zend_class_entry **aliases) /* {{{ */ { int i = 0; zend_trait_alias* cur_alias; @@ -1672,13 +1660,13 @@ static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce) cur_alias = ce->trait_aliases[i]; /** The trait for this alias has not been resolved, this means, this alias was not applied. Abort with an error. */ - if (!cur_alias->trait_method->ce) { + if (!aliases[i]) { if (cur_alias->alias) { /** Plain old inconsistency/typo/bug */ zend_error_noreturn(E_COMPILE_ERROR, "An alias (%s) was defined for method %s(), but this method does not exist", ZSTR_VAL(cur_alias->alias), - ZSTR_VAL(cur_alias->trait_method->method_name)); + ZSTR_VAL(cur_alias->trait_method.method_name)); } else { /** Here are two possible cases: 1) this is an attempt to modifiy the visibility @@ -1689,18 +1677,18 @@ static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce) as in the case where alias is set. */ lc_method_name = zend_string_tolower( - cur_alias->trait_method->method_name); + cur_alias->trait_method.method_name); if (zend_hash_exists(&ce->function_table, lc_method_name)) { zend_string_release_ex(lc_method_name, 0); zend_error_noreturn(E_COMPILE_ERROR, "The modifiers for the trait alias %s() need to be changed in the same statement in which the alias is defined. Error", - ZSTR_VAL(cur_alias->trait_method->method_name)); + ZSTR_VAL(cur_alias->trait_method.method_name)); } else { zend_string_release_ex(lc_method_name, 0); zend_error_noreturn(E_COMPILE_ERROR, "The modifiers of the trait method %s() are changed, but this method does not exist. Error", - ZSTR_VAL(cur_alias->trait_method->method_name)); + ZSTR_VAL(cur_alias->trait_method.method_name)); } } @@ -1713,19 +1701,29 @@ static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce) ZEND_API void zend_do_bind_traits(zend_class_entry *ce) /* {{{ */ { + HashTable **exclude_tables; + zend_class_entry **aliases; if (ce->num_traits == 0) { return; } /* complete initialization of trait strutures in ce */ - zend_traits_init_trait_structures(ce); + zend_traits_init_trait_structures(ce, &exclude_tables, &aliases); /* first care about all methods to be flattened into the class */ - zend_do_traits_method_binding(ce); + zend_do_traits_method_binding(ce, exclude_tables, aliases); /* Aliases which have not been applied indicate typos/bugs. */ - zend_do_check_for_inconsistent_traits_aliasing(ce); + zend_do_check_for_inconsistent_traits_aliasing(ce, aliases); + + if (aliases) { + efree(aliases); + } + + if (exclude_tables) { + efree(exclude_tables); + } /* then flatten the properties into it, to, mostly to notfiy developer about problems */ zend_do_traits_property_binding(ce); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 9031242345..ce0cd2d4a5 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -169,14 +169,11 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce) if (ce->trait_aliases) { size_t i = 0; while (ce->trait_aliases[i]) { - if (ce->trait_aliases[i]->trait_method) { - if (ce->trait_aliases[i]->trait_method->method_name) { - zend_string_release_ex(ce->trait_aliases[i]->trait_method->method_name, 0); - } - if (ce->trait_aliases[i]->trait_method->class_name) { - zend_string_release_ex(ce->trait_aliases[i]->trait_method->class_name, 0); - } - efree(ce->trait_aliases[i]->trait_method); + if (ce->trait_aliases[i]->trait_method.method_name) { + zend_string_release_ex(ce->trait_aliases[i]->trait_method.method_name, 0); + } + if (ce->trait_aliases[i]->trait_method.class_name) { + zend_string_release_ex(ce->trait_aliases[i]->trait_method.class_name, 0); } if (ce->trait_aliases[i]->alias) { @@ -191,21 +188,15 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce) } if (ce->trait_precedences) { - size_t i = 0; + int i = 0; + int j; while (ce->trait_precedences[i]) { - zend_string_release_ex(ce->trait_precedences[i]->trait_method->method_name, 0); - zend_string_release_ex(ce->trait_precedences[i]->trait_method->class_name, 0); - efree(ce->trait_precedences[i]->trait_method); - - if (ce->trait_precedences[i]->exclude_from_classes) { - size_t j = 0; - zend_trait_precedence *cur_precedence = ce->trait_precedences[i]; - while (cur_precedence->exclude_from_classes[j].class_name) { - zend_string_release_ex(cur_precedence->exclude_from_classes[j].class_name, 0); - j++; - } - efree(ce->trait_precedences[i]->exclude_from_classes); + zend_string_release_ex(ce->trait_precedences[i]->trait_method.method_name, 0); + zend_string_release_ex(ce->trait_precedences[i]->trait_method.class_name, 0); + + for (j = 0; j < ce->trait_precedences[i]->num_excludes; j++) { + zend_string_release_ex(ce->trait_precedences[i]->exclude_class_names[j], 0); } efree(ce->trait_precedences[i]); i++; diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index d1e9b5571c..707c49533f 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -437,8 +437,6 @@ static void zend_class_copy_ctor(zend_class_entry **pce) while (ce->trait_aliases[i]) { trait_aliases[i] = emalloc(sizeof(zend_trait_alias)); memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias)); - trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference)); - memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference)); i++; } trait_aliases[i] = NULL; @@ -455,28 +453,8 @@ static void zend_class_copy_ctor(zend_class_entry **pce) trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1)); i = 0; while (ce->trait_precedences[i]) { - trait_precedences[i] = emalloc(sizeof(zend_trait_precedence)); - memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence)); - trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference)); - memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference)); - - if (trait_precedences[i]->exclude_from_classes) { - zend_string **exclude_from_classes; - int j = 0; - - while (trait_precedences[i]->exclude_from_classes[j].class_name) { - j++; - } - exclude_from_classes = emalloc(sizeof(zend_string*) * (j + 1)); - j = 0; - while (trait_precedences[i]->exclude_from_classes[j].class_name) { - exclude_from_classes[j] = - trait_precedences[i]->exclude_from_classes[j].class_name; - j++; - } - exclude_from_classes[j] = NULL; - trait_precedences[i]->exclude_from_classes = (void*)exclude_from_classes; - } + trait_precedences[i] = emalloc(sizeof(zend_trait_precedence) + (ce->trait_precedences[i]->num_excludes - 1) * sizeof(zend_string*)); + memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence) + (ce->trait_precedences[i]->num_excludes - 1) * sizeof(zend_string*)); i++; } trait_precedences[i] = NULL; diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 3f405c6118..6190760049 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -648,19 +648,11 @@ static void zend_file_cache_serialize_class(zval *zv, q = *p; UNSERIALIZE_PTR(q); - if (q->trait_method) { - zend_trait_method_reference *m; - - SERIALIZE_PTR(q->trait_method); - m = q->trait_method; - UNSERIALIZE_PTR(m); - - if (m->method_name) { - SERIALIZE_STR(m->method_name); - } - if (m->class_name) { - SERIALIZE_STR(m->class_name); - } + if (q->trait_method.method_name) { + SERIALIZE_STR(q->trait_method.method_name); + } + if (q->trait_method.class_name) { + SERIALIZE_STR(q->trait_method.class_name); } if (q->alias) { @@ -672,6 +664,7 @@ static void zend_file_cache_serialize_class(zval *zv, if (ce->trait_precedences) { zend_trait_precedence **p, *q; + int j; SERIALIZE_PTR(ce->trait_precedences); p = ce->trait_precedences; @@ -682,32 +675,15 @@ static void zend_file_cache_serialize_class(zval *zv, q = *p; UNSERIALIZE_PTR(q); - if (q->trait_method) { - zend_trait_method_reference *m; - - SERIALIZE_PTR(q->trait_method); - m = q->trait_method; - UNSERIALIZE_PTR(m); - - if (m->method_name) { - SERIALIZE_STR(m->method_name); - } - if (m->class_name) { - SERIALIZE_STR(m->class_name); - } + if (q->trait_method.method_name) { + SERIALIZE_STR(q->trait_method.method_name); + } + if (q->trait_method.class_name) { + SERIALIZE_STR(q->trait_method.class_name); } - if (q->exclude_from_classes) { - zend_string **s; - - SERIALIZE_PTR(q->exclude_from_classes); - s = (zend_string**)q->exclude_from_classes; - UNSERIALIZE_PTR(s); - - while (*s) { - SERIALIZE_STR(*s); - s++; - } + for (j = 0; j < q->num_excludes; j++) { + SERIALIZE_STR(q->exclude_class_names[j]); } p++; } @@ -1278,18 +1254,11 @@ static void zend_file_cache_unserialize_class(zval *zv, UNSERIALIZE_PTR(*p); q = *p; - if (q->trait_method) { - zend_trait_method_reference *m; - - UNSERIALIZE_PTR(q->trait_method); - m = q->trait_method; - - if (m->method_name) { - UNSERIALIZE_STR(m->method_name); - } - if (m->class_name) { - UNSERIALIZE_STR(m->class_name); - } + if (q->trait_method.method_name) { + UNSERIALIZE_STR(q->trait_method.method_name); + } + if (q->trait_method.class_name) { + UNSERIALIZE_STR(q->trait_method.class_name); } if (q->alias) { @@ -1301,6 +1270,7 @@ static void zend_file_cache_unserialize_class(zval *zv, if (ce->trait_precedences) { zend_trait_precedence **p, *q; + int j; UNSERIALIZE_PTR(ce->trait_precedences); p = ce->trait_precedences; @@ -1309,30 +1279,15 @@ static void zend_file_cache_unserialize_class(zval *zv, UNSERIALIZE_PTR(*p); q = *p; - if (q->trait_method) { - zend_trait_method_reference *m; - - UNSERIALIZE_PTR(q->trait_method); - m = q->trait_method; - - if (m->method_name) { - UNSERIALIZE_STR(m->method_name); - } - if (m->class_name) { - UNSERIALIZE_STR(m->class_name); - } + if (q->trait_method.method_name) { + UNSERIALIZE_STR(q->trait_method.method_name); + } + if (q->trait_method.class_name) { + UNSERIALIZE_STR(q->trait_method.class_name); } - if (q->exclude_from_classes) { - zend_string **s; - - UNSERIALIZE_PTR(q->exclude_from_classes); - s = (zend_string**)q->exclude_from_classes; - - while (*s) { - UNSERIALIZE_STR(*s); - s++; - } + for (j = 0; j < q->num_excludes; j++) { + UNSERIALIZE_STR(q->exclude_class_names[j]); } p++; } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index ecd0da5163..f7310232e5 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -775,16 +775,11 @@ static void zend_persist_class_entry(zval *zv) if (ce->trait_aliases) { int i = 0; while (ce->trait_aliases[i]) { - if (ce->trait_aliases[i]->trait_method) { - if (ce->trait_aliases[i]->trait_method->method_name) { - zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->method_name); - } - if (ce->trait_aliases[i]->trait_method->class_name) { - zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method->class_name); - } - ce->trait_aliases[i]->trait_method->ce = NULL; - zend_accel_store(ce->trait_aliases[i]->trait_method, - sizeof(zend_trait_method_reference)); + if (ce->trait_aliases[i]->trait_method.method_name) { + zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method.method_name); + } + if (ce->trait_aliases[i]->trait_method.class_name) { + zend_accel_store_interned_string(ce->trait_aliases[i]->trait_method.class_name); } if (ce->trait_aliases[i]->alias) { @@ -800,26 +795,17 @@ static void zend_persist_class_entry(zval *zv) if (ce->trait_precedences) { int i = 0; + int j; while (ce->trait_precedences[i]) { - zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->method_name); - zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method->class_name); - ce->trait_precedences[i]->trait_method->ce = NULL; - zend_accel_store(ce->trait_precedences[i]->trait_method, - sizeof(zend_trait_method_reference)); - - if (ce->trait_precedences[i]->exclude_from_classes) { - int j = 0; - - while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) { - zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_from_classes[j].class_name); - j++; - } - zend_accel_store(ce->trait_precedences[i]->exclude_from_classes, - sizeof(zend_class_entry*) * (j + 1)); + zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method.method_name); + zend_accel_store_interned_string(ce->trait_precedences[i]->trait_method.class_name); + + for (j = 0; j < ce->trait_precedences[i]->num_excludes; j++) { + zend_accel_store_interned_string(ce->trait_precedences[i]->exclude_class_names[j]); } - zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence)); + zend_accel_store(ce->trait_precedences[i], sizeof(zend_trait_precedence) + (ce->trait_precedences[i]->num_excludes - 1) * sizeof(zend_string*)); i++; } zend_accel_store( diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 0291464c4e..4e08d754c7 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -345,14 +345,11 @@ static void zend_persist_class_entry_calc(zval *zv) if (ce->trait_aliases) { int i = 0; while (ce->trait_aliases[i]) { - if (ce->trait_aliases[i]->trait_method) { - if (ce->trait_aliases[i]->trait_method->method_name) { - ADD_INTERNED_STRING(ce->trait_aliases[i]->trait_method->method_name, 0); - } - if (ce->trait_aliases[i]->trait_method->class_name) { - ADD_INTERNED_STRING(ce->trait_aliases[i]->trait_method->class_name, 0); - } - ADD_SIZE(sizeof(zend_trait_method_reference)); + if (ce->trait_aliases[i]->trait_method.method_name) { + ADD_INTERNED_STRING(ce->trait_aliases[i]->trait_method.method_name, 0); + } + if (ce->trait_aliases[i]->trait_method.class_name) { + ADD_INTERNED_STRING(ce->trait_aliases[i]->trait_method.class_name, 0); } if (ce->trait_aliases[i]->alias) { @@ -366,22 +363,16 @@ static void zend_persist_class_entry_calc(zval *zv) if (ce->trait_precedences) { int i = 0; + int j; while (ce->trait_precedences[i]) { - ADD_INTERNED_STRING(ce->trait_precedences[i]->trait_method->method_name, 0); - ADD_INTERNED_STRING(ce->trait_precedences[i]->trait_method->class_name, 0); - ADD_SIZE(sizeof(zend_trait_method_reference)); - - if (ce->trait_precedences[i]->exclude_from_classes) { - int j = 0; - - while (ce->trait_precedences[i]->exclude_from_classes[j].class_name) { - ADD_INTERNED_STRING(ce->trait_precedences[i]->exclude_from_classes[j].class_name, 0); - j++; - } - ADD_SIZE(sizeof(zend_class_entry*) * (j + 1)); + ADD_INTERNED_STRING(ce->trait_precedences[i]->trait_method.method_name, 0); + ADD_INTERNED_STRING(ce->trait_precedences[i]->trait_method.class_name, 0); + + for (j = 0; j < ce->trait_precedences[i]->num_excludes; j++) { + ADD_INTERNED_STRING(ce->trait_precedences[i]->exclude_class_names[j], 0); } - ADD_SIZE(sizeof(zend_trait_precedence)); + ADD_SIZE(sizeof(zend_trait_precedence) + (ce->trait_precedences[i]->num_excludes - 1) * sizeof(zend_string*)); i++; } ADD_SIZE(sizeof(zend_trait_precedence*) * (i + 1)); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index cba4f1d54a..87220dd7d3 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4939,12 +4939,12 @@ ZEND_METHOD(reflection_class, getTraitAliases) array_init(return_value); while (ce->trait_aliases[i]) { zend_string *mname; - zend_trait_method_reference *cur_ref = ce->trait_aliases[i]->trait_method; + zend_trait_method_reference *cur_ref = &ce->trait_aliases[i]->trait_method; if (ce->trait_aliases[i]->alias) { - mname = zend_string_alloc(ZSTR_LEN(cur_ref->ce->name) + ZSTR_LEN(cur_ref->method_name) + 2, 0); - snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(cur_ref->ce->name), ZSTR_VAL(cur_ref->method_name)); + mname = zend_string_alloc(ZSTR_LEN(cur_ref->class_name) + ZSTR_LEN(cur_ref->method_name) + 2, 0); + snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(cur_ref->class_name), ZSTR_VAL(cur_ref->method_name)); add_assoc_str_ex(return_value, ZSTR_VAL(ce->trait_aliases[i]->alias), ZSTR_LEN(ce->trait_aliases[i]->alias), mname); } i++; |