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

Reply via email to