diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 6fa0d47c7bd7f..c6e129490bba7 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1487,6 +1487,7 @@ #[AllowDynamicProperties] final class __PHP_Incomplete_Class { + private function __construct() {} } class AssertionError extends Error diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index e467710f72f91..1ef332e36a25a 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit basic_functions.stub.php instead. - * Stub hash: 8d1c2a735f412f8571675c6b025c3a418b68fb65 + * Stub hash: 905d53e204a8ab18d493d4730ec2bceb27dc98bb * Has decl header: yes */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) @@ -2191,6 +2191,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sapi_windows_generate_ctrl_event ZEND_END_ARG_INFO() #endif +#define arginfo_class___PHP_Incomplete_Class___construct arginfo_tmpfile + ZEND_FRAMELESS_FUNCTION(min, 2); static const zend_frameless_function_info frameless_function_infos_min[] = { @@ -2893,6 +2895,7 @@ ZEND_FUNCTION(sapi_windows_cp_is_utf8); ZEND_FUNCTION(sapi_windows_set_ctrl_handler); ZEND_FUNCTION(sapi_windows_generate_ctrl_event); #endif +ZEND_METHOD(__PHP_Incomplete_Class, __construct); static const zend_function_entry ext_functions[] = { ZEND_FE(set_time_limit, arginfo_set_time_limit) @@ -3509,6 +3512,11 @@ static const zend_function_entry ext_functions[] = { ZEND_FE_END }; +static const zend_function_entry class___PHP_Incomplete_Class_methods[] = { + ZEND_ME(__PHP_Incomplete_Class, __construct, arginfo_class___PHP_Incomplete_Class___construct, ZEND_ACC_PRIVATE) + ZEND_FE_END +}; + static void register_basic_functions_symbols(int module_number) { REGISTER_LONG_CONSTANT("EXTR_OVERWRITE", PHP_EXTR_OVERWRITE, CONST_PERSISTENT); @@ -3984,7 +3992,7 @@ static zend_class_entry *register_class___PHP_Incomplete_Class(void) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "__PHP_Incomplete_Class", NULL); + INIT_CLASS_ENTRY(ce, "__PHP_Incomplete_Class", class___PHP_Incomplete_Class_methods); class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES); zend_string *attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, true); diff --git a/ext/standard/basic_functions_decl.h b/ext/standard/basic_functions_decl.h index 9e6fb0def4472..01b4d2bcdb248 100644 --- a/ext/standard/basic_functions_decl.h +++ b/ext/standard/basic_functions_decl.h @@ -1,8 +1,8 @@ /* This is a generated file, edit basic_functions.stub.php instead. - * Stub hash: 8d1c2a735f412f8571675c6b025c3a418b68fb65 */ + * Stub hash: 905d53e204a8ab18d493d4730ec2bceb27dc98bb */ -#ifndef ZEND_BASIC_FUNCTIONS_DECL_8d1c2a735f412f8571675c6b025c3a418b68fb65_H -#define ZEND_BASIC_FUNCTIONS_DECL_8d1c2a735f412f8571675c6b025c3a418b68fb65_H +#ifndef ZEND_BASIC_FUNCTIONS_DECL_905d53e204a8ab18d493d4730ec2bceb27dc98bb_H +#define ZEND_BASIC_FUNCTIONS_DECL_905d53e204a8ab18d493d4730ec2bceb27dc98bb_H typedef enum zend_enum_RoundingMode { ZEND_ENUM_RoundingMode_HalfAwayFromZero = 1, @@ -15,4 +15,4 @@ typedef enum zend_enum_RoundingMode { ZEND_ENUM_RoundingMode_PositiveInfinity = 8, } zend_enum_RoundingMode; -#endif /* ZEND_BASIC_FUNCTIONS_DECL_8d1c2a735f412f8571675c6b025c3a418b68fb65_H */ +#endif /* ZEND_BASIC_FUNCTIONS_DECL_905d53e204a8ab18d493d4730ec2bceb27dc98bb_H */ diff --git a/ext/standard/incomplete_class.c b/ext/standard/incomplete_class.c index 228e03fbe863e..65a903833573f 100644 --- a/ext/standard/incomplete_class.c +++ b/ext/standard/incomplete_class.c @@ -95,6 +95,21 @@ static zend_function *incomplete_class_get_method(zend_object **object, zend_str } /* }}} */ +/* {{{ Private constructor preventing instantiation */ +static ZEND_COLD zend_function *incomplete_class_get_constructor(zend_object *object) /* {{{ */ +{ + zend_throw_error(NULL, "Instantiation of class __PHP_Incomplete_Class is not allowed"); + return NULL; +} + +ZEND_COLD ZEND_METHOD(__PHP_Incomplete_Class, __construct) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_throw_error(NULL, "Instantiation of class __PHP_Incomplete_Class is not allowed"); +} +/* }}} */ + /* {{{ php_create_incomplete_class */ static zend_object *php_create_incomplete_object(zend_class_entry *class_type) { @@ -111,12 +126,15 @@ static zend_object *php_create_incomplete_object(zend_class_entry *class_type) PHPAPI void php_register_incomplete_class_handlers(void) { memcpy(&php_incomplete_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + + php_incomplete_object_handlers.get_constructor = incomplete_class_get_constructor; php_incomplete_object_handlers.read_property = incomplete_class_get_property; php_incomplete_object_handlers.has_property = incomplete_class_has_property; php_incomplete_object_handlers.unset_property = incomplete_class_unset_property; php_incomplete_object_handlers.write_property = incomplete_class_write_property; php_incomplete_object_handlers.get_property_ptr_ptr = incomplete_class_get_property_ptr_ptr; php_incomplete_object_handlers.get_method = incomplete_class_get_method; + php_incomplete_object_handlers.clone_obj = NULL; php_ce_incomplete_class->create_object = php_create_incomplete_object; } diff --git a/ext/standard/tests/serialize/incomplete_class.phpt b/ext/standard/tests/serialize/incomplete_class.phpt index 2ead760508cfe..24b0b228bcb20 100644 --- a/ext/standard/tests/serialize/incomplete_class.phpt +++ b/ext/standard/tests/serialize/incomplete_class.phpt @@ -3,7 +3,8 @@ --FILE-- test2); echo "Done\n"; ?> --EXPECTF-- -object(__PHP_Incomplete_Class)#%d (0) { +object(__PHP_Incomplete_Class)#%d (1) { + ["__PHP_Incomplete_Class_Name"]=> + string(7) "Unknown" } -The script tried to modify a property on an incomplete object. Please ensure that the class definition "unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition +The script tried to modify a property on an incomplete object. Please ensure that the class definition "Unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition -Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in %s on line %d +Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "Unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in %s on line %d NULL -Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in %s on line %d +Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "Unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in %s on line %d NULL Done diff --git a/ext/standard/tests/serialize/incomplete_class_clone.phpt b/ext/standard/tests/serialize/incomplete_class_clone.phpt new file mode 100644 index 0000000000000..0ddeb4fc5a5ea --- /dev/null +++ b/ext/standard/tests/serialize/incomplete_class_clone.phpt @@ -0,0 +1,19 @@ +--TEST-- +__PHP_Incomplete_Class cannot be cloned +--FILE-- +isCloneable()); +var_dump(clone($o)); +?> +--EXPECTF-- +string(22) "__PHP_Incomplete_Class" +bool(false) + +Fatal error: Uncaught Error: Trying to clone an uncloneable object of class __PHP_Incomplete_Class in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/ext/standard/tests/serialize/incomplete_class_constructor.phpt b/ext/standard/tests/serialize/incomplete_class_constructor.phpt new file mode 100644 index 0000000000000..1cd0db5426a38 --- /dev/null +++ b/ext/standard/tests/serialize/incomplete_class_constructor.phpt @@ -0,0 +1,14 @@ +--TEST-- +__PHP_Incomplete_Class cannot be instantiated +--FILE-- + +--EXPECTF-- +string(22) "__PHP_Incomplete_Class" + +Fatal error: Uncaught Error: Instantiation of class __PHP_Incomplete_Class is not allowed in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/ext/standard/tests/serialize/incomplete_class_newinstancewithoutconstructor.phpt b/ext/standard/tests/serialize/incomplete_class_newinstancewithoutconstructor.phpt new file mode 100644 index 0000000000000..9c76ae30da265 --- /dev/null +++ b/ext/standard/tests/serialize/incomplete_class_newinstancewithoutconstructor.phpt @@ -0,0 +1,12 @@ +--TEST-- +ReflectionClass::newInstanceWithoutConstructor cannot instantiate __PHP_Incomplete_Class +--FILE-- +newInstanceWithoutConstructor(); +--EXPECTF-- +Fatal error: Uncaught ReflectionException: Class __PHP_Incomplete_Class is an internal class marked as final that cannot be instantiated without invoking its constructor in %s:%d +Stack trace: +#0 %s(%d): ReflectionClass->newInstanceWithoutConstructor() +#1 {main} + thrown in %s on line %d diff --git a/ext/standard/tests/serialize/serialization_objects_006.phpt b/ext/standard/tests/serialize/serialization_objects_006.phpt index 131bf85658faa..292365b193918 100644 --- a/ext/standard/tests/serialize/serialization_objects_006.phpt +++ b/ext/standard/tests/serialize/serialization_objects_006.phpt @@ -2,16 +2,18 @@ Behaviour of incomplete class is preserved even when it was not created by unserialize(). --FILE-- p); echo "Done"; ?> --EXPECTF-- -object(__PHP_Incomplete_Class)#%d (0) { +object(__PHP_Incomplete_Class)#1 (1) { + ["__PHP_Incomplete_Class_Name"]=> + string(7) "Unknown" } -Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in %s on line %d +Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "Unknown" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in %s on line %d NULL Done