Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4842ede

Browse files
Improve magic __get and property type inconsistency error message
Fixes GH-9388 Closes GH-9436
1 parent e17a7ac commit 4842ede

File tree

7 files changed

+44
-6
lines changed

7 files changed

+44
-6
lines changed

‎NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.3.0alpha1
44

5+
- Core:
6+
. Fixed bug GH-9388 (Improve unset property and __get type incompatibility
7+
error message). (ilutov)
8+
59
- Opcache:
610
. Added start, restart and force restart time to opcache's
711
phpinfo section. (Mikhail Galanin)

‎Zend/tests/type_declarations/typed_properties_030.phpt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ unset($foo->bar); # ok
1919
var_dump($foo->bar); # not okay, __get is nasty
2020
?>
2121
--EXPECTF--
22-
Fatal error: Uncaught TypeError: Cannot assign string to property Foo::$bar of type int in %s:%d
22+
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
2323
Stack trace:
2424
#0 {main}
2525
thrown in %s on line %d

‎Zend/tests/type_declarations/typed_properties_040.phpt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var_dump($foo->bar);
2020
--EXPECTF--
2121
string(3) "bar"
2222

23-
Fatal error: Uncaught TypeError: Cannot assign null to property Foo::$bar of type int in %s:%d
23+
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
2424
Stack trace:
2525
#0 {main}
2626
thrown in %s on line %d

‎Zend/tests/type_declarations/typed_properties_074.phpt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ object(Test)#1 (1) {
3232
["val"]=>
3333
uninitialized(int)
3434
}
35-
Cannot assign string to property Test::$val of type int
35+
Value of type string returned from Test::__get() must be compatible with unset property Test::$val of type int
3636
object(Test)#1 (1) {
3737
["prop"]=>
3838
&string(1) "x"

‎Zend/zend_execute.c‎

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,23 @@ ZEND_COLD zend_never_inline void zend_verify_property_type_error(zend_property_i
830830
zend_string_release(type_str);
831831
}
832832

833+
ZEND_COLD zend_never_inline void zend_magic_get_property_type_inconsistency_error(zend_property_info *info, zval *property)
834+
{
835+
/* 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) */
836+
if (EG(exception)) {
837+
return;
838+
}
839+
840+
zend_string *type_str = zend_type_to_string(info->type);
841+
zend_type_error("Value of type %s returned from %s::__get() must be compatible with unset property %s::$%s of type %s",
842+
zend_zval_type_name(property),
843+
ZSTR_VAL(info->ce->name),
844+
ZSTR_VAL(info->ce->name),
845+
zend_get_unmangled_property_name(info->name),
846+
ZSTR_VAL(type_str));
847+
zend_string_release(type_str);
848+
}
849+
833850
ZEND_COLD void zend_match_unhandled_error(zval *value)
834851
{
835852
smart_str msg = {0};
@@ -3560,7 +3577,7 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze
35603577
return variable_ptr;
35613578
}
35623579

3563-
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict) {
3580+
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_contextcontext) {
35643581
zval *val = orig_val;
35653582
if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) {
35663583
int result;
@@ -3591,10 +3608,20 @@ ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_inf
35913608
}
35923609
}
35933610

3594-
zend_verify_property_type_error(prop_info, val);
3611+
if (EXPECTED(context == ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT)) {
3612+
zend_verify_property_type_error(prop_info, val);
3613+
} else {
3614+
ZEND_ASSERT(context == ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_MAGIC_GET);
3615+
zend_magic_get_property_type_inconsistency_error(prop_info, val);
3616+
}
3617+
35953618
return 0;
35963619
}
35973620

3621+
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict) {
3622+
return zend_verify_prop_assignable_by_ref_ex(prop_info, orig_val, strict, ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT);
3623+
}
3624+
35983625
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop)
35993626
{
36003627
zend_property_info_list *list;

‎Zend/zend_execute.h‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, u
6565
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim);
6666

6767
ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict);
68+
69+
typedef enum {
70+
ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT,
71+
ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_MAGIC_GET,
72+
} zend_verify_prop_assignable_by_ref_context;
73+
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);
6874
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict);
6975

7076
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);
449455

450456
ZEND_API bool zend_verify_property_type(zend_property_info *info, zval *property, bool strict);
451457
ZEND_COLD void zend_verify_property_type_error(zend_property_info *info, zval *property);
458+
ZEND_COLD void zend_magic_get_property_type_inconsistency_error(zend_property_info *info, zval *property);
452459

453460
#define ZEND_REF_ADD_TYPE_SOURCE(ref, source) \
454461
zend_ref_add_type_source(&ZEND_REF_TYPE_SOURCES(ref), source)

‎Zend/zend_object_handlers.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
726726
}
727727

728728
if (UNEXPECTED(prop_info)) {
729-
zend_verify_prop_assignable_by_ref(prop_info, retval, (zobj->ce->__get->common.fn_flags & ZEND_ACC_STRICT_TYPES) != 0);
729+
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);
730730
}
731731

732732
OBJ_RELEASE(zobj);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /