From d586441d902ebabf2300b6724a2217e07bb12803 Mon Sep 17 00:00:00 2001 From: Ferenc Kovacs Date: Wed, 23 Jul 2014 07:45:02 +0200 Subject: [PATCH 1/3] ReflectionClass::newInstanceWithoutConstructor() should be allowed to instantiate every class except those internal classes with a final __construct() --- ext/reflection/php_reflection.c | 4 ++-- .../ReflectionClass_newInstanceWithoutConstructor.phpt | 7 ++++++- ext/reflection/tests/bug64007.phpt | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 02a19c0aaab..8ccd5e6f620 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4308,8 +4308,8 @@ ZEND_METHOD(reflection_class, newInstanceWithoutConstructor) METHOD_NOTSTATIC(reflection_class_ptr); GET_REFLECTION_OBJECT_PTR(ce); - if (ce->create_object != NULL) { - zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s is an internal class that cannot be instantiated without invoking its constructor", ce->name); + if (ce->create_object != NULL && ce->ce_flags & ZEND_ACC_FINAL_CLASS) { + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s is an internal class with a final __construct thus cannot be instantiated without invoking its constructor", ce->name); } object_init_ex(return_value, ce); diff --git a/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt b/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt index 1932dbfaf18..580c5730312 100644 --- a/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt +++ b/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt @@ -20,13 +20,18 @@ var_dump($class->newInstanceWithoutConstructor()); $class = new ReflectionClass('DateTime'); var_dump($class->newInstanceWithoutConstructor()); + +$class = new ReflectionClass('Generator'); +var_dump($class->newInstanceWithoutConstructor()); --EXPECTF-- object(Foo)#%d (0) { } object(stdClass)#%d (0) { } +object(DateTime)#%d (0) { +} -Fatal error: Uncaught exception 'ReflectionException' with message 'Class DateTime is an internal class that cannot be instantiated without invoking its constructor' in %sReflectionClass_newInstanceWithoutConstructor.php:%d +Fatal error: Uncaught exception 'ReflectionException' with message 'Class Generator is an internal class with a final __construct thus cannot be instantiated without invoking its constructor' in %sReflectionClass_newInstanceWithoutConstructor.php:%d Stack trace: #0 %sReflectionClass_newInstanceWithoutConstructor.php(%d): ReflectionClass->newInstanceWithoutConstructor() #1 {main} diff --git a/ext/reflection/tests/bug64007.phpt b/ext/reflection/tests/bug64007.phpt index 32ec6a56107..df8609385ef 100644 --- a/ext/reflection/tests/bug64007.phpt +++ b/ext/reflection/tests/bug64007.phpt @@ -14,6 +14,6 @@ $generator = $reflection->newInstance(); var_dump($generator); ?> --EXPECTF-- -string(97) "Class Generator is an internal class that cannot be instantiated without invoking its constructor" +string(%d) "Class Generator is an internal class with a final __construct thus cannot be instantiated without invoking its constructor" Catchable fatal error: The "Generator" class is reserved for internal use and cannot be manually instantiated in %sbug64007.php on line %d From d18b16244c0cf3daf806bbad5a459fbd3195f152 Mon Sep 17 00:00:00 2001 From: Ferenc Kovacs Date: Wed, 30 Jul 2014 10:08:26 +0200 Subject: [PATCH 2/3] update the exception message to better match the actual check --- ext/reflection/php_reflection.c | 2 +- .../tests/ReflectionClass_newInstanceWithoutConstructor.phpt | 2 +- ext/reflection/tests/bug64007.phpt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 8ccd5e6f620..8e5fcadef43 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4309,7 +4309,7 @@ ZEND_METHOD(reflection_class, newInstanceWithoutConstructor) GET_REFLECTION_OBJECT_PTR(ce); if (ce->create_object != NULL && ce->ce_flags & ZEND_ACC_FINAL_CLASS) { - zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s is an internal class with a final __construct thus cannot be instantiated without invoking its constructor", ce->name); + zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s is an internal class marked as final that cannot be instantiated without invoking its constructor", ce->name); } object_init_ex(return_value, ce); diff --git a/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt b/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt index 580c5730312..dfe3e7f8f7c 100644 --- a/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt +++ b/ext/reflection/tests/ReflectionClass_newInstanceWithoutConstructor.phpt @@ -31,7 +31,7 @@ object(stdClass)#%d (0) { object(DateTime)#%d (0) { } -Fatal error: Uncaught exception 'ReflectionException' with message 'Class Generator is an internal class with a final __construct thus cannot be instantiated without invoking its constructor' in %sReflectionClass_newInstanceWithoutConstructor.php:%d +Fatal error: Uncaught exception 'ReflectionException' with message 'Class Generator is an internal class marked as final that cannot be instantiated without invoking its constructor' in %sReflectionClass_newInstanceWithoutConstructor.php:%d Stack trace: #0 %sReflectionClass_newInstanceWithoutConstructor.php(%d): ReflectionClass->newInstanceWithoutConstructor() #1 {main} diff --git a/ext/reflection/tests/bug64007.phpt b/ext/reflection/tests/bug64007.phpt index df8609385ef..ae3ec503289 100644 --- a/ext/reflection/tests/bug64007.phpt +++ b/ext/reflection/tests/bug64007.phpt @@ -14,6 +14,6 @@ $generator = $reflection->newInstance(); var_dump($generator); ?> --EXPECTF-- -string(%d) "Class Generator is an internal class with a final __construct thus cannot be instantiated without invoking its constructor" +string(%d) "Class Generator is an internal class marked as final that cannot be instantiated without invoking its constructor" Catchable fatal error: The "Generator" class is reserved for internal use and cannot be manually instantiated in %sbug64007.php on line %d From d649b785d63a58ba09dbb38b1279e4e0424b7d51 Mon Sep 17 00:00:00 2001 From: Ferenc Kovacs Date: Wed, 30 Jul 2014 10:45:35 +0200 Subject: [PATCH 3/3] NEWS entry for #67713 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index abaeaba4e77..d69f0d85773 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,10 @@ PHP NEWS - Phar: . Fixed bug #67587 (Redirection loop on nginx with FPM). (Christian Weiske) +- Reflection: + . Implemented FR #67713 (loosen the restrictions on + ReflectionClass::newInstanceWithoutConstructor()). (Ferenc) + - SPL: . Fixed bug #67539 (ArrayIterator use-after-free due to object change during sorting). (research at insighti dot org, Laruence)