1 |
vip-ire |
1.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 |
|
|
|