mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Improve magic __get and property type inconsistency error message
Fixes GH-9388 Closes GH-9436
This commit is contained in:
parent
e17a7ac54b
commit
4842edeae4
7 changed files with 44 additions and 6 deletions
4
NEWS
4
NEWS
|
@ -2,6 +2,10 @@ PHP NEWS
|
||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||
?? ??? ????, PHP 8.3.0alpha1
|
?? ??? ????, PHP 8.3.0alpha1
|
||||||
|
|
||||||
|
- Core:
|
||||||
|
. Fixed bug GH-9388 (Improve unset property and __get type incompatibility
|
||||||
|
error message). (ilutov)
|
||||||
|
|
||||||
- Opcache:
|
- Opcache:
|
||||||
. Added start, restart and force restart time to opcache's
|
. Added start, restart and force restart time to opcache's
|
||||||
phpinfo section. (Mikhail Galanin)
|
phpinfo section. (Mikhail Galanin)
|
||||||
|
|
|
@ -19,7 +19,7 @@ unset($foo->bar); # ok
|
||||||
var_dump($foo->bar); # not okay, __get is nasty
|
var_dump($foo->bar); # not okay, __get is nasty
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught TypeError: Cannot assign string to property Foo::$bar of type int in %s:%d
|
Fatal error: Uncaught TypeError: Value of type string returned from Foo::__get() must be compatible with unset property Foo::$bar of type int in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 {main}
|
#0 {main}
|
||||||
thrown in %s on line %d
|
thrown in %s on line %d
|
||||||
|
|
|
@ -20,7 +20,7 @@ var_dump($foo->bar);
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
string(3) "bar"
|
string(3) "bar"
|
||||||
|
|
||||||
Fatal error: Uncaught TypeError: Cannot assign null to property Foo::$bar of type int in %s:%d
|
Fatal error: Uncaught TypeError: Value of type null returned from Foo::__get() must be compatible with unset property Foo::$bar of type int in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 {main}
|
#0 {main}
|
||||||
thrown in %s on line %d
|
thrown in %s on line %d
|
||||||
|
|
|
@ -32,7 +32,7 @@ object(Test)#1 (1) {
|
||||||
["val"]=>
|
["val"]=>
|
||||||
uninitialized(int)
|
uninitialized(int)
|
||||||
}
|
}
|
||||||
Cannot assign string to property Test::$val of type int
|
Value of type string returned from Test::__get() must be compatible with unset property Test::$val of type int
|
||||||
object(Test)#1 (1) {
|
object(Test)#1 (1) {
|
||||||
["prop"]=>
|
["prop"]=>
|
||||||
&string(1) "x"
|
&string(1) "x"
|
||||||
|
|
|
@ -830,6 +830,23 @@ ZEND_COLD zend_never_inline void zend_verify_property_type_error(zend_property_i
|
||||||
zend_string_release(type_str);
|
zend_string_release(type_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZEND_COLD zend_never_inline void zend_magic_get_property_type_inconsistency_error(zend_property_info *info, zval *property)
|
||||||
|
{
|
||||||
|
/* we _may_ land here in case reading already errored and runtime cache thus has not been updated (i.e. it contains a valid but unrelated info) */
|
||||||
|
if (EG(exception)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_string *type_str = zend_type_to_string(info->type);
|
||||||
|
zend_type_error("Value of type %s returned from %s::__get() must be compatible with unset property %s::$%s of type %s",
|
||||||
|
zend_zval_type_name(property),
|
||||||
|
ZSTR_VAL(info->ce->name),
|
||||||
|
ZSTR_VAL(info->ce->name),
|
||||||
|
zend_get_unmangled_property_name(info->name),
|
||||||
|
ZSTR_VAL(type_str));
|
||||||
|
zend_string_release(type_str);
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_COLD void zend_match_unhandled_error(zval *value)
|
ZEND_COLD void zend_match_unhandled_error(zval *value)
|
||||||
{
|
{
|
||||||
smart_str msg = {0};
|
smart_str msg = {0};
|
||||||
|
@ -3560,7 +3577,7 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze
|
||||||
return variable_ptr;
|
return variable_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict) {
|
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref_ex(zend_property_info *prop_info, zval *orig_val, bool strict, zend_verify_prop_assignable_by_ref_context context) {
|
||||||
zval *val = orig_val;
|
zval *val = orig_val;
|
||||||
if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {
|
if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {
|
||||||
int result;
|
int result;
|
||||||
|
@ -3591,10 +3608,20 @@ ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_inf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_verify_property_type_error(prop_info, val);
|
if (EXPECTED(context == ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT)) {
|
||||||
|
zend_verify_property_type_error(prop_info, val);
|
||||||
|
} else {
|
||||||
|
ZEND_ASSERT(context == ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_MAGIC_GET);
|
||||||
|
zend_magic_get_property_type_inconsistency_error(prop_info, val);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict) {
|
||||||
|
return zend_verify_prop_assignable_by_ref_ex(prop_info, orig_val, strict, ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT);
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop)
|
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop)
|
||||||
{
|
{
|
||||||
zend_property_info_list *list;
|
zend_property_info_list *list;
|
||||||
|
|
|
@ -65,6 +65,12 @@ ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, u
|
||||||
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim);
|
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim);
|
||||||
|
|
||||||
ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict);
|
ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT,
|
||||||
|
ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_MAGIC_GET,
|
||||||
|
} zend_verify_prop_assignable_by_ref_context;
|
||||||
|
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref_ex(zend_property_info *prop_info, zval *orig_val, bool strict, zend_verify_prop_assignable_by_ref_context context);
|
||||||
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict);
|
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict);
|
||||||
|
|
||||||
ZEND_API ZEND_COLD void zend_throw_ref_type_error_zval(zend_property_info *prop, zval *zv);
|
ZEND_API ZEND_COLD void zend_throw_ref_type_error_zval(zend_property_info *prop, zval *zv);
|
||||||
|
@ -449,6 +455,7 @@ ZEND_API int ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *call);
|
||||||
|
|
||||||
ZEND_API bool zend_verify_property_type(zend_property_info *info, zval *property, bool strict);
|
ZEND_API bool zend_verify_property_type(zend_property_info *info, zval *property, bool strict);
|
||||||
ZEND_COLD void zend_verify_property_type_error(zend_property_info *info, zval *property);
|
ZEND_COLD void zend_verify_property_type_error(zend_property_info *info, zval *property);
|
||||||
|
ZEND_COLD void zend_magic_get_property_type_inconsistency_error(zend_property_info *info, zval *property);
|
||||||
|
|
||||||
#define ZEND_REF_ADD_TYPE_SOURCE(ref, source) \
|
#define ZEND_REF_ADD_TYPE_SOURCE(ref, source) \
|
||||||
zend_ref_add_type_source(&ZEND_REF_TYPE_SOURCES(ref), source)
|
zend_ref_add_type_source(&ZEND_REF_TYPE_SOURCES(ref), source)
|
||||||
|
|
|
@ -726,7 +726,7 @@ call_getter:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNEXPECTED(prop_info)) {
|
if (UNEXPECTED(prop_info)) {
|
||||||
zend_verify_prop_assignable_by_ref(prop_info, retval, (zobj->ce->__get->common.fn_flags & ZEND_ACC_STRICT_TYPES) != 0);
|
zend_verify_prop_assignable_by_ref_ex(prop_info, retval, (zobj->ce->__get->common.fn_flags & ZEND_ACC_STRICT_TYPES) != 0, ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_MAGIC_GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ_RELEASE(zobj);
|
OBJ_RELEASE(zobj);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue