Commit: 6c0508f8d5d5a62adb37a76bc682c94540199ee3 Author: Dmitry Stogov <dmi...@zend.com> Wed, 5 Sep 2012 09:58:22 +0400 Parents: ff0aa24054c166de64993ef608ccbb8486c64ba5 Branches: PHP-5.4 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=6c0508f8d5d5a62adb37a76bc682c94540199ee3 Log: Fixed bug #62907 (Double free when use traits) Bugs: https://bugs.php.net/62907 Changed paths: M NEWS M Zend/tests/bug62907.phpt M Zend/zend_compile.c M Zend/zend_compile.h M Zend/zend_opcode.c Diff: diff --git a/NEWS b/NEWS index e09664a..22d3f66 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ PHP NEWS some builtin classes). (Laruence) . Fixed bug #62955 (Only one directive is loaded from "Per Directory Values" Windows registry). (aserbulov at parallels dot com) + . Fixed bug #62907 (Double free when use traits). (Dmitry) - SOAP . Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice). diff --git a/Zend/tests/bug62907.phpt b/Zend/tests/bug62907.phpt index c519a54..53ab17c 100644 --- a/Zend/tests/bug62907.phpt +++ b/Zend/tests/bug62907.phpt @@ -1,7 +1,5 @@ --TEST-- Bug #62907 (Double free when use traits) ---XFAIL-- -bug is not fixed yet --FILE-- <?php function __autoload($name) { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index bf458e1..c39d8ea 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3878,10 +3878,10 @@ static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, && (zend_binary_strcasecmp(aliases[i]->trait_method->method_name, aliases[i]->trait_method->mname_len, fn->common.function_name, fnname_len) == 0)) { fn_copy = *fn; function_add_ref(&fn_copy); - /* this function_name is never destroyed, because its refcount - greater than 1 and classes are always destoyed before the - traits they use */ + /* this function_name is never destroyed, because ZEND_ACC_ALIAS + flag is set */ fn_copy.common.function_name = aliases[i]->alias; + fn_copy.common.fn_flags |= ZEND_ACC_ALIAS; /* if it is 0, no modifieres has been changed */ if (aliases[i]->modifiers) { @@ -3914,6 +3914,7 @@ static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, /* is not in hashtable, thus, function is not to be excluded */ fn_copy = *fn; function_add_ref(&fn_copy); + fn_copy.common.fn_flags |= ZEND_ACC_ALIAS; /* apply aliases which are not qualified by a class name, or which have not * alias name, just setting visibility */ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index f164122..79ace0c 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -207,6 +207,8 @@ typedef struct _zend_try_catch_element { #define ZEND_ACC_RETURN_REFERENCE 0x4000000 #define ZEND_ACC_DONE_PASS_TWO 0x8000000 +#define ZEND_ACC_ALIAS 0x10000000 + char *zend_visibility_string(zend_uint fn_flags); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 19fd71e..6eab0ae 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -267,6 +267,15 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce) } } +static int zend_clear_trait_method_name(zend_op_array *op_array TSRMLS_DC) +{ + if (op_array->function_name && (op_array->fn_flags & ZEND_ACC_ALIAS) == 0) { + efree(op_array->function_name); + op_array->function_name = NULL; + } + return 0; +} + ZEND_API void destroy_zend_class(zend_class_entry **pce) { zend_class_entry *ce = *pce; @@ -298,6 +307,9 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce) } zend_hash_destroy(&ce->properties_info); str_efree(ce->name); + if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) { + zend_hash_apply(&ce->function_table, (apply_func_t)zend_clear_trait_method_name TSRMLS_CC); + } zend_hash_destroy(&ce->function_table); zend_hash_destroy(&ce->constants_table); if (ce->num_interfaces > 0 && ce->interfaces) { @@ -387,7 +399,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) } efree(op_array->opcodes); - if (op_array->function_name) { + if (op_array->function_name && (op_array->fn_flags & ZEND_ACC_ALIAS) == 0) { efree((char*)op_array->function_name); } if (op_array->doc_comment) { -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php