summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/bug54268.phpt35
-rw-r--r--Zend/zend_execute_API.c2
-rw-r--r--Zend/zend_hash.c22
3 files changed, 47 insertions, 12 deletions
diff --git a/Zend/tests/bug54268.phpt b/Zend/tests/bug54268.phpt
new file mode 100644
index 0000000000..b544cd882a
--- /dev/null
+++ b/Zend/tests/bug54268.phpt
@@ -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
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 03d250cce7..e15344a4f0 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -289,7 +289,9 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
zend_hash_reverse_apply(EG(class_table), (apply_func_t) zend_cleanup_user_class_data TSRMLS_CC);
zend_cleanup_internal_classes(TSRMLS_C);
}
+ } zend_end_try();
+ zend_try {
zend_vm_stack_destroy(TSRMLS_C);
zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC);
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 4ee3cdeb5c..73c45a286c 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -563,9 +563,17 @@ ZEND_API void zend_hash_clean(HashTable *ht)
IS_CONSISTENT(ht);
- SET_INCONSISTENT(HT_CLEANING);
-
p = ht->pListHead;
+
+ if (ht->nTableMask) {
+ 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;
@@ -577,16 +585,6 @@ ZEND_API void zend_hash_clean(HashTable *ht)
}
pefree(q, ht->persistent);
}
- if (ht->nTableMask) {
- 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.