Promote incomplete class to modification to Error

In line with engine diagnostic promotions, property writes throw
an Error exception, while reads throw a warning.
This commit is contained in:
Nikita Popov 2020-08-28 11:14:43 +02:00
parent f965e20059
commit 32315c247f
5 changed files with 74 additions and 47 deletions

View File

@ -3,9 +3,21 @@ Bug #71841 (EG(error_zval) is not handled well)
--FILE--
<?php
$z = unserialize('O:1:"A":0:{}');
@var_dump($z->e.=0);
@var_dump(++$z->x);
@var_dump($z->y++);
try {
var_dump($z->e.=0);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(++$z->x);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump($z->y++);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
$y = array(PHP_INT_MAX => 0);
try {
@ -25,9 +37,9 @@ try {
}
?>
--EXPECT--
NULL
NULL
NULL
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
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
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
Cannot add element to the array as the next element is already occupied
Cannot add element to the array as the next element is already occupied
Cannot add element to the array as the next element is already occupied

View File

@ -19,8 +19,7 @@
#include "php_incomplete_class.h"
#define INCOMPLETE_CLASS_MSG \
"The script tried to execute a method or " \
"access a property of an incomplete object. " \
"The script tried to %s on an incomplete object. " \
"Please ensure that the class definition \"%s\" of the object " \
"you are trying to operate on was loaded _before_ " \
"unserialize() gets called or provide an autoloader " \
@ -29,20 +28,21 @@
PHPAPI zend_class_entry *php_ce_incomplete_class;
static zend_object_handlers php_incomplete_object_handlers;
static void incomplete_class_message(zend_object *object, int error_type)
static void incomplete_class_message(zend_object *object)
{
zend_string *class_name = php_lookup_class_name(object);
php_error_docref(NULL, error_type, INCOMPLETE_CLASS_MSG,
class_name ? ZSTR_VAL(class_name) : "unknown");
php_error_docref(NULL, E_WARNING, INCOMPLETE_CLASS_MSG,
"access a property", class_name ? ZSTR_VAL(class_name) : "unknown");
if (class_name) {
zend_string_release_ex(class_name, 0);
}
}
static void throw_incomplete_class_error(zend_object *object)
static void throw_incomplete_class_error(zend_object *object, const char *what)
{
zend_string *class_name = php_lookup_class_name(object);
zend_throw_error(NULL, INCOMPLETE_CLASS_MSG, class_name ? ZSTR_VAL(class_name) : "unknown");
zend_throw_error(NULL, INCOMPLETE_CLASS_MSG,
what, class_name ? ZSTR_VAL(class_name) : "unknown");
if (class_name) {
zend_string_release_ex(class_name, 0);
}
@ -50,7 +50,7 @@ static void throw_incomplete_class_error(zend_object *object)
static zval *incomplete_class_get_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv) /* {{{ */
{
incomplete_class_message(object, E_NOTICE);
incomplete_class_message(object);
if (type == BP_VAR_W || type == BP_VAR_RW) {
ZVAL_ERROR(rv);
@ -63,34 +63,34 @@ static zval *incomplete_class_get_property(zend_object *object, zend_string *mem
static zval *incomplete_class_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot) /* {{{ */
{
incomplete_class_message(object, E_NOTICE);
throw_incomplete_class_error(object, "modify a property");
return value;
}
/* }}} */
static zval *incomplete_class_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot) /* {{{ */
{
incomplete_class_message(object, E_NOTICE);
throw_incomplete_class_error(object, "modify a property");
return &EG(error_zval);
}
/* }}} */
static void incomplete_class_unset_property(zend_object *object, zend_string *member, void **cache_slot) /* {{{ */
{
incomplete_class_message(object, E_NOTICE);
throw_incomplete_class_error(object, "modify a property");
}
/* }}} */
static int incomplete_class_has_property(zend_object *object, zend_string *member, int check_empty, void **cache_slot) /* {{{ */
{
incomplete_class_message(object, E_NOTICE);
incomplete_class_message(object);
return 0;
}
/* }}} */
static zend_function *incomplete_class_get_method(zend_object **object, zend_string *method, const zval *key) /* {{{ */
{
throw_incomplete_class_error(*object);
throw_incomplete_class_error(*object, "call a method");
return NULL;
}
/* }}} */

View File

@ -7,7 +7,11 @@ $d = serialize(new __PHP_Incomplete_Class);
$o = unserialize($d);
var_dump($o);
$o->test = "a";
try {
$o->test = "a";
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($o->test);
var_dump($o->test2);
@ -16,12 +20,11 @@ echo "Done\n";
--EXPECTF--
object(__PHP_Incomplete_Class)#%d (0) {
}
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
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
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
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
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
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

View File

@ -34,18 +34,34 @@ var_dump($incomplete);
var_dump(is_object($incomplete));
var_dump($incomplete->p);
$ref2 = "ref1.original";
$incomplete->p = &$ref2;
try {
$ref2 = "ref1.original";
$incomplete->p = &$ref2;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($incomplete->p);
$ref2 = "ref1.changed";
var_dump($incomplete->p);
$incomplete->p = "p.changed";
try {
$incomplete->p = "p.changed";
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($ref1);
var_dump(isset($incomplete->x));
$incomplete->x = "x.new";
try {
$incomplete->x = "x.new";
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump(isset($incomplete->x));
unset($incomplete->x);
try {
unset($incomplete->x);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($incomplete->x);
try {
@ -83,31 +99,27 @@ object(__PHP_Incomplete_Class)#%d (2) {
}
bool(true)
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
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
NULL
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
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
NULL
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
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
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
NULL
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
NULL
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
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
string(9) "p.changed"
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
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
bool(false)
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
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
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
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
bool(false)
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
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
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
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
NULL
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
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
Done

View File

@ -12,6 +12,6 @@ echo "Done";
object(__PHP_Incomplete_Class)#%d (0) {
}
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
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