summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2016-03-20 04:55:11 -0700
committerXinchen Hui <laruence@gmail.com>2016-03-20 04:55:11 -0700
commit0cacbae4104b04a522cbfb417a8c0c5326d8ca50 (patch)
tree97ba6976383e2277cb9a06d23853709e2cff260d
parent24f63b1c320cd5d079ba7de40482a9f2067a1c7a (diff)
parent9564998e490092fdefa6630944e38692c75e30de (diff)
downloadphp-git-0cacbae4104b04a522cbfb417a8c0c5326d8ca50.tar.gz
Merge branch 'PHP-7.0'
-rw-r--r--Zend/tests/bug71859.phpt28
-rw-r--r--Zend/zend_objects_API.c12
2 files changed, 32 insertions, 8 deletions
diff --git a/Zend/tests/bug71859.phpt b/Zend/tests/bug71859.phpt
new file mode 100644
index 0000000000..5b62209a1b
--- /dev/null
+++ b/Zend/tests/bug71859.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #71859 (zend_objects_store_call_destructors operates on realloced memory, crashing)
+--FILE--
+<?php
+class constructs_in_destructor {
+ public function __destruct() {
+ //We are now in zend_objects_store_call_destructors
+ //This causes a realloc in zend_objects_store_put
+ for ($i = 0; $i < 10000; ++$i) {
+ $GLOBALS["a$i"] = new stdClass;
+ }
+ //Returns to zend_objects_store_call_destructors, to access freed memory.
+ }
+}
+
+$a = new constructs_in_destructor;
+//Create cycle so destructors are ran only in zend_objects_store_call_destructors
+$a->a = $a;
+
+// Create some objects so zend_objects_store_call_destructors has something
+// to do after constructs_in_destructor is destroyed.
+for ($i = 0; $i < 200; ++$i) {
+ $GLOBALS["b$i"] = new stdClass;
+}
+?>
+okey
+--EXPECT--
+okey
diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c
index 6ca190eabe..00d9425f18 100644
--- a/Zend/zend_objects_API.c
+++ b/Zend/zend_objects_API.c
@@ -44,12 +44,9 @@ ZEND_API void zend_objects_store_destroy(zend_objects_store *objects)
ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects)
{
if (objects->top > 1) {
- zend_object **obj_ptr = objects->object_buckets + 1;
- zend_object **end = objects->object_buckets + objects->top;
-
- do {
- zend_object *obj = *obj_ptr;
-
+ uint32_t i;
+ for (i = 1; i < objects->top; i++) {
+ zend_object *obj = objects->object_buckets[i];
if (IS_OBJ_VALID(obj)) {
if (!(GC_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) {
GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED;
@@ -58,8 +55,7 @@ ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects)
GC_REFCOUNT(obj)--;
}
}
- obj_ptr++;
- } while (obj_ptr != end);
+ }
}
}