diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug64720.phpt | 9 | ||||
-rw-r--r-- | Zend/tests/bug68652.phpt | 11 | ||||
-rw-r--r-- | Zend/tests/bug74053.phpt | 43 | ||||
-rw-r--r-- | Zend/zend.c | 1 | ||||
-rw-r--r-- | Zend/zend_globals.h | 4 | ||||
-rw-r--r-- | Zend/zend_objects_API.c | 5 | ||||
-rw-r--r-- | main/main.c | 2 |
8 files changed, 62 insertions, 15 deletions
@@ -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 |