Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ext/standard/basic_functions.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,7 @@
#[AllowDynamicProperties]
final class __PHP_Incomplete_Class
{
private function __construct() {}
}

class AssertionError extends Error
Expand Down
12 changes: 10 additions & 2 deletions ext/standard/basic_functions_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions ext/standard/basic_functions_decl.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions ext/standard/incomplete_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
}
Expand Down
13 changes: 8 additions & 5 deletions ext/standard/tests/serialize/incomplete_class.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
--FILE--
<?php

$d = serialize(new __PHP_Incomplete_Class);
$orig = unserialize('O:7:"Unknown":0:{}');
$d = serialize($orig);
$o = unserialize($d);
var_dump($o);

Expand All @@ -18,13 +19,15 @@ var_dump($o->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
19 changes: 19 additions & 0 deletions ext/standard/tests/serialize/incomplete_class_clone.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
__PHP_Incomplete_Class cannot be cloned
--FILE--
<?php
$o = unserialize('O:3:"Foo":0:{}');
var_dump($o::class);

$rc = new ReflectionClass("__PHP_Incomplete_Class");
var_dump($rc->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
14 changes: 14 additions & 0 deletions ext/standard/tests/serialize/incomplete_class_constructor.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
__PHP_Incomplete_Class cannot be instantiated
--FILE--
<?php
var_dump(__PHP_Incomplete_Class::class);
var_dump(new __PHP_Incomplete_Class());
?>
--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
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
ReflectionClass::newInstanceWithoutConstructor cannot instantiate __PHP_Incomplete_Class
--FILE--
<?php
$rc = new ReflectionClass("__PHP_Incomplete_Class");
$rc->newInstanceWithoutConstructor();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please always keep the closing PHP tag in tests:

Suggested change
$rc->newInstanceWithoutConstructor();
$rc->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
8 changes: 5 additions & 3 deletions ext/standard/tests/serialize/serialization_objects_006.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@
Behaviour of incomplete class is preserved even when it was not created by unserialize().
--FILE--
<?php
$a = new __PHP_Incomplete_Class;
$a = unserialize('O:7:"Unknown":0:{}');
var_dump($a);
var_dump($a->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
Loading