summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug64720.phpt9
-rw-r--r--Zend/tests/bug68652.phpt11
-rw-r--r--Zend/tests/bug74053.phpt43
-rw-r--r--Zend/zend.c1
-rw-r--r--Zend/zend_globals.h4
-rw-r--r--Zend/zend_objects_API.c5
-rw-r--r--main/main.c2
8 files changed, 62 insertions, 15 deletions
diff --git a/NEWS b/NEWS
index aba91c3dec..cd3df458c8 100644
--- a/NEWS
+++ b/NEWS
@@ -28,6 +28,8 @@ PHP NEWS
. Fixed bug #73973 (assertion error in debug_zval_dump). (andrewnester)
. Fixed bug #73987 (Method compatibility check looks to original
definition and not parent). (pmmaga)
+ . Fixed bug #74053 (Corrupted class entries on shutdown when a destructor
+ spawns another object). (jim at commercebyte dot com)
- BCMath:
. Fixed bug #46564 (bcmod truncates fractionals). (liborm85)
diff --git a/Zend/tests/bug64720.phpt b/Zend/tests/bug64720.phpt
index 45dee3e8c4..efe3379bd4 100644
--- a/Zend/tests/bug64720.phpt
+++ b/Zend/tests/bug64720.phpt
@@ -44,9 +44,6 @@ $foo = new Foo();
$bar = new Bar();
$bar->test();
?>
---EXPECTF--
-Fatal error: Uncaught Error: Access to undeclared static property: Stat::$requests in %sbug64720.php:12
-Stack trace:
-#0 [internal function]: Stat->__destruct()
-#1 {main}
- thrown in %sbug64720.php on line 12
+OK
+--EXPECT--
+OK
diff --git a/Zend/tests/bug68652.phpt b/Zend/tests/bug68652.phpt
index 8e54af2e34..de450b102a 100644
--- a/Zend/tests/bug68652.phpt
+++ b/Zend/tests/bug68652.phpt
@@ -36,11 +36,6 @@ class Bar {
$foo = new Foo();
?>
---EXPECTF--
-Fatal error: Uncaught Error: Access to undeclared static property: Bar::$instance in %sbug68652.php:%d
-Stack trace:
-#0 %s(%d): Bar::getInstance()
-#1 [internal function]: Foo->__destruct()
-#2 {main}
- thrown in %sbug68652.php on line %d
-
+OK
+--EXPECT--
+OK
diff --git a/Zend/tests/bug74053.phpt b/Zend/tests/bug74053.phpt
new file mode 100644
index 0000000000..b1936a58e9
--- /dev/null
+++ b/Zend/tests/bug74053.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Bug #74053 (Corrupted class entries on shutdown when a destructor spawns another object)
+--FILE--
+<?php
+class b {
+ function __destruct() {
+ echo "b::destruct\n";
+ }
+}
+class a {
+ static $b;
+ static $new;
+ static $max = 10;
+ function __destruct() {
+ if (self::$max-- <= 0) return;
+ echo "a::destruct\n";
+ self::$b = new b;
+ self::$new[] = new a;
+ }
+}
+new a;
+?>
+--EXPECT--
+a::destruct
+b::destruct
+a::destruct
+b::destruct
+a::destruct
+b::destruct
+a::destruct
+b::destruct
+a::destruct
+b::destruct
+a::destruct
+b::destruct
+a::destruct
+b::destruct
+a::destruct
+b::destruct
+a::destruct
+b::destruct
+a::destruct
+b::destruct
diff --git a/Zend/zend.c b/Zend/zend.c
index bcbca562b1..c5236ba7ea 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -648,6 +648,7 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{
#ifdef ZEND_WIN32
zend_get_windows_version_info(&executor_globals->windows_version_info);
#endif
+ executor_globals->flags = EG_FLAGS_INITIAL;
}
/* }}} */
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index 083875fc2c..3440edfc69 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -214,6 +214,7 @@ struct _zend_executor_globals {
zend_bool active;
zend_bool valid_symbol_table;
+ zend_uchar flags;
zend_long assertions;
@@ -235,6 +236,9 @@ struct _zend_executor_globals {
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
+#define EG_FLAGS_INITIAL 0x00
+#define EG_FLAGS_IN_SHUTDOWN 0x01
+
struct _zend_ini_scanner_globals {
zend_file_handle *yy_in;
zend_file_handle *yy_out;
diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c
index 858113aabd..3aedba1bda 100644
--- a/Zend/zend_objects_API.c
+++ b/Zend/zend_objects_API.c
@@ -111,7 +111,10 @@ ZEND_API void zend_objects_store_put(zend_object *object)
{
int handle;
- if (EG(objects_store).free_list_head != -1) {
+ /* When in shutdown sequesnce - do not reuse previously freed handles, to make sure
+ * the dtors for newly created objects are called in zend_objects_store_call_destructors() loop
+ */
+ if (!(EG(flags) & EG_FLAGS_IN_SHUTDOWN) && EG(objects_store).free_list_head != -1) {
handle = EG(objects_store).free_list_head;
EG(objects_store).free_list_head = GET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[handle]);
} else {
diff --git a/main/main.c b/main/main.c
index a8674a5d11..9e139eff72 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1799,6 +1799,8 @@ void php_request_shutdown(void *dummy)
{
zend_bool report_memleaks;
+ EG(flags) |= EG_FLAGS_IN_SHUTDOWN;
+
report_memleaks = PG(report_memleaks);
/* EG(current_execute_data) points into nirvana and therefore cannot be safely accessed