summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2017-02-10 10:31:43 +0300
committerDmitry Stogov <dmitry@zend.com>2017-02-10 10:31:43 +0300
commitc39147d136d67bb3b9e36cdbef7944d831570af4 (patch)
treeb962155ec30daf11c4ed3a7655e705caa770a90f
parent1760b031eab5cac900bdbb9c72827b572fce52cf (diff)
parent1b1399c95d1358b23f234c14e84dda9b5007904e (diff)
downloadphp-git-c39147d136d67bb3b9e36cdbef7944d831570af4.tar.gz
Fixed bug #74053 (Corrupted class entries on shutdown when a destructor spawns another object). (jim at commercebyte dot com)
Merge branch 'master' of github.com:commercebyte/php-src * 'master' of github.com:commercebyte/php-src: Added EG(flags) - executor global flags EG_FLAGS_IN_SHUTDOWN - is set when PHP is in shutdown state newly added zend_object_store.no_reuse is redefined as a global zend_object_store_no_reuse, to avoid alignment issues Alignment fix, as per @nikic The test scripts bug64720.phpt and bug68652.phpt were relying on the buggy behavior, when PHP returns "Undefined static property" error due to class entry corruption. With my fix for bug 74053, both tests return no errors now, I corrected the EXPECTF accordingly Bug Fix: Corrupted class entries on shutdown when a destructor spawns another object (C) 2017 CommerceByte Consulting
-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