]> granicus.if.org Git - php/commitdiff
Fixed bug #54268 (Double free when destroy_zend_class fails)
authorDmitry Stogov <dmitry@php.net>
Fri, 15 Apr 2011 12:43:20 +0000 (12:43 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 15 Apr 2011 12:43:20 +0000 (12:43 +0000)
Zend/tests/bug54268.phpt [new file with mode: 0644]
Zend/zend_execute_API.c
Zend/zend_hash.c

diff --git a/Zend/tests/bug54268.phpt b/Zend/tests/bug54268.phpt
new file mode 100644 (file)
index 0000000..b544cd8
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+Bug #54268 (Double free when destroy_zend_class fails)
+--INI--
+memory_limit=8M
+--SKIPIF--
+<?php
+$zend_mm_enabled = getenv("USE_ZEND_ALLOC");
+if ($zend_mm_enabled === "0") {
+       die("skip Zend MM disabled");
+}
+?>
+--FILE--
+<?php
+class DestructableObject
+{
+        public function __destruct()
+        {
+                DestructableObject::__destruct();
+        }
+}
+class DestructorCreator
+{
+        public function __destruct()
+        {
+                $this->test = new DestructableObject;
+        }
+}
+class Test
+{
+        public static $mystatic;
+}
+$x = new Test();
+Test::$mystatic = new DestructorCreator();
+--EXPECTF--
+Fatal error: Allowed memory size of %s bytes exhausted%s(tried to allocate %s bytes) in %s on line %d
index 0ad62a2e00287c428721ec0b85b489fd4ccaafd8..3717f43fbfff9c8f6b68bae4214a2f26f9fce940 100644 (file)
@@ -296,7 +296,9 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
                        zend_hash_reverse_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC);
                }
                zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC);
+       } zend_end_try();
 
+       zend_try {
                zend_vm_stack_destroy(TSRMLS_C);
 
                zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC);
index 204ac0cc39f5958a60a6f4aae1583c8bed61349e..be514ffedfa2fe95bf8d13c50f4e616522c3bd5c 100644 (file)
@@ -545,9 +545,15 @@ ZEND_API void zend_hash_clean(HashTable *ht)
 
        IS_CONSISTENT(ht);
 
-       SET_INCONSISTENT(HT_CLEANING);
-
        p = ht->pListHead;
+
+       memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
+       ht->pListHead = NULL;
+       ht->pListTail = NULL;
+       ht->nNumOfElements = 0;
+       ht->nNextFreeElement = 0;
+       ht->pInternalPointer = NULL;
+
        while (p != NULL) {
                q = p;
                p = p->pListNext;
@@ -559,14 +565,6 @@ ZEND_API void zend_hash_clean(HashTable *ht)
                }
                pefree(q, ht->persistent);
        }
-       memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
-       ht->pListHead = NULL;
-       ht->pListTail = NULL;
-       ht->nNumOfElements = 0;
-       ht->nNextFreeElement = 0;
-       ht->pInternalPointer = NULL;
-
-       SET_INCONSISTENT(HT_OK);
 }
 
 /* This function is used by the various apply() functions.