Skip to content

Commit 32315c2

Browse files
committed
Promote incomplete class to modification to Error
In line with engine diagnostic promotions, property writes throw an Error exception, while reads throw a warning.
1 parent f965e20 commit 32315c2

File tree

5 files changed

+72
-45
lines changed

5 files changed

+72
-45
lines changed

Zend/tests/bug71841.phpt

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,21 @@ Bug #71841 (EG(error_zval) is not handled well)
33
--FILE--
44
<?php
55
$z = unserialize('O:1:"A":0:{}');
6-
@var_dump($z->e.=0);
7-
@var_dump(++$z->x);
8-
@var_dump($z->y++);
6+
try {
7+
var_dump($z->e.=0);
8+
} catch (Error $e) {
9+
echo $e->getMessage(), "\n";
10+
}
11+
try {
12+
var_dump(++$z->x);
13+
} catch (Error $e) {
14+
echo $e->getMessage(), "\n";
15+
}
16+
try {
17+
var_dump($z->y++);
18+
} catch (Error $e) {
19+
echo $e->getMessage(), "\n";
20+
}
921

1022
$y = array(PHP_INT_MAX => 0);
1123
try {
@@ -25,9 +37,9 @@ try {
2537
}
2638
?>
2739
--EXPECT--
28-
NULL
29-
NULL
30-
NULL
40+
The script tried to modify a property on an incomplete object. Please ensure that the class definition "A" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
41+
The script tried to modify a property on an incomplete object. Please ensure that the class definition "A" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
42+
The script tried to modify a property on an incomplete object. Please ensure that the class definition "A" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
3143
Cannot add element to the array as the next element is already occupied
3244
Cannot add element to the array as the next element is already occupied
3345
Cannot add element to the array as the next element is already occupied

ext/standard/incomplete_class.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
#include "php_incomplete_class.h"
2020

2121
#define INCOMPLETE_CLASS_MSG \
22-
"The script tried to execute a method or " \
23-
"access a property of an incomplete object. " \
22+
"The script tried to %s on an incomplete object. " \
2423
"Please ensure that the class definition \"%s\" of the object " \
2524
"you are trying to operate on was loaded _before_ " \
2625
"unserialize() gets called or provide an autoloader " \
@@ -29,28 +28,29 @@
2928
PHPAPI zend_class_entry *php_ce_incomplete_class;
3029
static zend_object_handlers php_incomplete_object_handlers;
3130

32-
static void incomplete_class_message(zend_object *object, int error_type)
31+
static void incomplete_class_message(zend_object *object)
3332
{
3433
zend_string *class_name = php_lookup_class_name(object);
35-
php_error_docref(NULL, error_type, INCOMPLETE_CLASS_MSG,
36-
class_name ? ZSTR_VAL(class_name) : "unknown");
34+
php_error_docref(NULL, E_WARNING, INCOMPLETE_CLASS_MSG,
35+
"access a property", class_name ? ZSTR_VAL(class_name) : "unknown");
3736
if (class_name) {
3837
zend_string_release_ex(class_name, 0);
3938
}
4039
}
4140

42-
static void throw_incomplete_class_error(zend_object *object)
41+
static void throw_incomplete_class_error(zend_object *object, const char *what)
4342
{
4443
zend_string *class_name = php_lookup_class_name(object);
45-
zend_throw_error(NULL, INCOMPLETE_CLASS_MSG, class_name ? ZSTR_VAL(class_name) : "unknown");
44+
zend_throw_error(NULL, INCOMPLETE_CLASS_MSG,
45+
what, class_name ? ZSTR_VAL(class_name) : "unknown");
4646
if (class_name) {
4747
zend_string_release_ex(class_name, 0);
4848
}
4949
}
5050

5151
static zval *incomplete_class_get_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv) /* {{{ */
5252
{
53-
incomplete_class_message(object, E_NOTICE);
53+
incomplete_class_message(object);
5454

5555
if (type == BP_VAR_W || type == BP_VAR_RW) {
5656
ZVAL_ERROR(rv);
@@ -63,34 +63,34 @@ static zval *incomplete_class_get_property(zend_object *object, zend_string *mem
6363

6464
static zval *incomplete_class_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot) /* {{{ */
6565
{
66-
incomplete_class_message(object, E_NOTICE);
66+
throw_incomplete_class_error(object, "modify a property");
6767
return value;
6868
}
6969
/* }}} */
7070

7171
static zval *incomplete_class_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot) /* {{{ */
7272
{
73-
incomplete_class_message(object, E_NOTICE);
73+
throw_incomplete_class_error(object, "modify a property");
7474
return &EG(error_zval);
7575
}
7676
/* }}} */
7777

7878
static void incomplete_class_unset_property(zend_object *object, zend_string *member, void **cache_slot) /* {{{ */
7979
{
80-
incomplete_class_message(object, E_NOTICE);
80+
throw_incomplete_class_error(object, "modify a property");
8181
}
8282
/* }}} */
8383

8484
static int incomplete_class_has_property(zend_object *object, zend_string *member, int check_empty, void **cache_slot) /* {{{ */
8585
{
86-
incomplete_class_message(object, E_NOTICE);
86+
incomplete_class_message(object);
8787
return 0;
8888
}
8989
/* }}} */
9090

9191
static zend_function *incomplete_class_get_method(zend_object **object, zend_string *method, const zval *key) /* {{{ */
9292
{
93-
throw_incomplete_class_error(*object);
93+
throw_incomplete_class_error(*object, "call a method");
9494
return NULL;
9595
}
9696
/* }}} */

ext/standard/tests/serialize/incomplete_class.phpt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ $d = serialize(new __PHP_Incomplete_Class);
77
$o = unserialize($d);
88
var_dump($o);
99

10-
$o->test = "a";
10+
try {
11+
$o->test = "a";
12+
} catch (Error $e) {
13+
echo $e->getMessage(), "\n";
14+
}
1115
var_dump($o->test);
1216
var_dump($o->test2);
1317

@@ -16,12 +20,11 @@ echo "Done\n";
1620
--EXPECTF--
1721
object(__PHP_Incomplete_Class)#%d (0) {
1822
}
23+
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
1924

20-
Notice: main(): The script tried to execute a method or access a property of 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
21-
22-
Notice: main(): The script tried to execute a method or access a property of 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
25+
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
2326
NULL
2427

25-
Notice: main(): The script tried to execute a method or access a property of 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
28+
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
2629
NULL
2730
Done

ext/standard/tests/serialize/serialization_objects_005.phpt

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,34 @@ var_dump($incomplete);
3434
var_dump(is_object($incomplete));
3535
var_dump($incomplete->p);
3636

37-
$ref2 = "ref1.original";
38-
$incomplete->p = &$ref2;
37+
try {
38+
$ref2 = "ref1.original";
39+
$incomplete->p = &$ref2;
40+
} catch (Error $e) {
41+
echo $e->getMessage(), "\n";
42+
}
3943
var_dump($incomplete->p);
4044
$ref2 = "ref1.changed";
4145
var_dump($incomplete->p);
42-
$incomplete->p = "p.changed";
46+
try {
47+
$incomplete->p = "p.changed";
48+
} catch (Error $e) {
49+
echo $e->getMessage(), "\n";
50+
}
4351
var_dump($ref1);
4452

4553
var_dump(isset($incomplete->x));
46-
$incomplete->x = "x.new";
54+
try {
55+
$incomplete->x = "x.new";
56+
} catch (Error $e) {
57+
echo $e->getMessage(), "\n";
58+
}
4759
var_dump(isset($incomplete->x));
48-
unset($incomplete->x);
60+
try {
61+
unset($incomplete->x);
62+
} catch (Error $e) {
63+
echo $e->getMessage(), "\n";
64+
}
4965
var_dump($incomplete->x);
5066

5167
try {
@@ -83,31 +99,27 @@ object(__PHP_Incomplete_Class)#%d (2) {
8399
}
84100
bool(true)
85101

86-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
102+
Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "C" 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
87103
NULL
104+
The script tried to modify a property on an incomplete object. Please ensure that the class definition "C" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
88105

89-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
90-
91-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
106+
Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "C" 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
92107
NULL
93108

94-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
109+
Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "C" 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
95110
NULL
96-
97-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
111+
The script tried to modify a property on an incomplete object. Please ensure that the class definition "C" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
98112
string(9) "p.changed"
99113

100-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
114+
Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "C" 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
101115
bool(false)
116+
The script tried to modify a property on an incomplete object. Please ensure that the class definition "C" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
102117

103-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
104-
105-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
118+
Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "C" 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
106119
bool(false)
120+
The script tried to modify a property on an incomplete object. Please ensure that the class definition "C" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
107121

108-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
109-
110-
Notice: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" 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
122+
Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "C" 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
111123
NULL
112-
The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "C" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
124+
The script tried to call a method on an incomplete object. Please ensure that the class definition "C" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition
113125
Done

ext/standard/tests/serialize/serialization_objects_006.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ echo "Done";
1212
object(__PHP_Incomplete_Class)#%d (0) {
1313
}
1414

15-
Notice: main(): The script tried to execute a method or access a property of 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
15+
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
1616
NULL
1717
Done

0 commit comments

Comments
 (0)