1 |
From 92e5b10c41668b1ceb55030a76cb74d41dac82d3 Mon Sep 17 00:00:00 2001 |
2 |
From: Dmitry Stogov <dmitry@php.net> |
3 |
Date: Fri, 15 Apr 2011 12:43:20 +0000 |
4 |
Subject: [PATCH] Fixed bug #54268 (Double free when destroy_zend_class fails) |
5 |
|
6 |
--- |
7 |
Zend/tests/bug54268.phpt | 35 +++++++++++++++++++++++++++++++++++ |
8 |
Zend/zend_execute_API.c | 2 ++ |
9 |
Zend/zend_hash.c | 18 ++++++++---------- |
10 |
3 files changed, 45 insertions(+), 10 deletions(-) |
11 |
create mode 100644 Zend/tests/bug54268.phpt |
12 |
|
13 |
diff --git a/Zend/tests/bug54268.phpt b/Zend/tests/bug54268.phpt |
14 |
new file mode 100644 |
15 |
index 0000000..b544cd8 |
16 |
--- /dev/null |
17 |
+++ b/Zend/tests/bug54268.phpt |
18 |
@@ -0,0 +1,35 @@ |
19 |
+--TEST-- |
20 |
+Bug #54268 (Double free when destroy_zend_class fails) |
21 |
+--INI-- |
22 |
+memory_limit=8M |
23 |
+--SKIPIF-- |
24 |
+<?php |
25 |
+$zend_mm_enabled = getenv("USE_ZEND_ALLOC"); |
26 |
+if ($zend_mm_enabled === "0") { |
27 |
+ die("skip Zend MM disabled"); |
28 |
+} |
29 |
+?> |
30 |
+--FILE-- |
31 |
+<?php |
32 |
+class DestructableObject |
33 |
+{ |
34 |
+ public function __destruct() |
35 |
+ { |
36 |
+ DestructableObject::__destruct(); |
37 |
+ } |
38 |
+} |
39 |
+class DestructorCreator |
40 |
+{ |
41 |
+ public function __destruct() |
42 |
+ { |
43 |
+ $this->test = new DestructableObject; |
44 |
+ } |
45 |
+} |
46 |
+class Test |
47 |
+{ |
48 |
+ public static $mystatic; |
49 |
+} |
50 |
+$x = new Test(); |
51 |
+Test::$mystatic = new DestructorCreator(); |
52 |
+--EXPECTF-- |
53 |
+Fatal error: Allowed memory size of %s bytes exhausted%s(tried to allocate %s bytes) in %s on line %d |
54 |
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c |
55 |
index 0ad62a2..3717f43 100644 |
56 |
--- a/Zend/zend_execute_API.c |
57 |
+++ b/Zend/zend_execute_API.c |
58 |
@@ -296,7 +296,9 @@ void shutdown_executor(TSRMLS_D) /* {{{ */ |
59 |
zend_hash_reverse_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC); |
60 |
} |
61 |
zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC); |
62 |
+ } zend_end_try(); |
63 |
|
64 |
+ zend_try { |
65 |
zend_vm_stack_destroy(TSRMLS_C); |
66 |
|
67 |
zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC); |
68 |
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c |
69 |
index 204ac0c..be514ff 100644 |
70 |
--- a/Zend/zend_hash.c |
71 |
+++ b/Zend/zend_hash.c |
72 |
@@ -545,9 +545,15 @@ ZEND_API void zend_hash_clean(HashTable *ht) |
73 |
|
74 |
IS_CONSISTENT(ht); |
75 |
|
76 |
- SET_INCONSISTENT(HT_CLEANING); |
77 |
- |
78 |
p = ht->pListHead; |
79 |
+ |
80 |
+ memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *)); |
81 |
+ ht->pListHead = NULL; |
82 |
+ ht->pListTail = NULL; |
83 |
+ ht->nNumOfElements = 0; |
84 |
+ ht->nNextFreeElement = 0; |
85 |
+ ht->pInternalPointer = NULL; |
86 |
+ |
87 |
while (p != NULL) { |
88 |
q = p; |
89 |
p = p->pListNext; |
90 |
@@ -559,14 +565,6 @@ ZEND_API void zend_hash_clean(HashTable *ht) |
91 |
} |
92 |
pefree(q, ht->persistent); |
93 |
} |
94 |
- memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *)); |
95 |
- ht->pListHead = NULL; |
96 |
- ht->pListTail = NULL; |
97 |
- ht->nNumOfElements = 0; |
98 |
- ht->nNextFreeElement = 0; |
99 |
- ht->pInternalPointer = NULL; |
100 |
- |
101 |
- SET_INCONSISTENT(HT_OK); |
102 |
} |
103 |
|
104 |
/* This function is used by the various apply() functions. |
105 |
-- |
106 |
1.7.11.5 |
107 |
|