From 2156b062dea75e29fcc80d35fae607f5b0925f8c Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 2 Aug 2026 20:55:35 +0100 Subject: [PATCH 1/2] Zend: add tests for ZPP class-string specifier --- ...lass-string_zpp_specifier_strict_mode.phpt | 51 +++++++++++++++++++ .../class-string_zpp_specifier_weak_mode.phpt | 49 ++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 ext/zend_test/tests/zpp/class-string_zpp_specifier_strict_mode.phpt create mode 100644 ext/zend_test/tests/zpp/class-string_zpp_specifier_weak_mode.phpt diff --git a/ext/zend_test/tests/zpp/class-string_zpp_specifier_strict_mode.phpt b/ext/zend_test/tests/zpp/class-string_zpp_specifier_strict_mode.phpt new file mode 100644 index 000000000000..3dcd833ea16f --- /dev/null +++ b/ext/zend_test/tests/zpp/class-string_zpp_specifier_strict_mode.phpt @@ -0,0 +1,51 @@ +--TEST-- +Test class string ZPP specifier +--EXTENSIONS-- +zend_test +--FILE-- +getMessage(), PHP_EOL; + } +} + +?> +--EXPECTF-- +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 1 given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 42 given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 73.5 given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, string given + +Warning: Array to string conversion in %s on line %d +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, Array given +Error: Object of class stdClass could not be converted to string +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, S class given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, Resource id #2 given diff --git a/ext/zend_test/tests/zpp/class-string_zpp_specifier_weak_mode.phpt b/ext/zend_test/tests/zpp/class-string_zpp_specifier_weak_mode.phpt new file mode 100644 index 000000000000..3959fa07c94a --- /dev/null +++ b/ext/zend_test/tests/zpp/class-string_zpp_specifier_weak_mode.phpt @@ -0,0 +1,49 @@ +--TEST-- +Test class string ZPP specifier +--EXTENSIONS-- +zend_test +--FILE-- +getMessage(), PHP_EOL; + } +} + +?> +--EXPECTF-- +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 1 given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 42 given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 73.5 given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, string given + +Warning: Array to string conversion in %s on line %d +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, Array given +Error: Object of class stdClass could not be converted to string +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, S class given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, Resource id #2 given From 624e7f8df6248f6f241f6e475be32719715f65c9 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 2 Aug 2026 21:11:02 +0100 Subject: [PATCH 2/2] Zend: handle non-string arguments for ZPP class-string specifier as expected This doesn't behave like any of the other specifiers, as it doesn't respect strict_types, emit a deprecation for null, or reject arrays --- Zend/zend_API.c | 12 +++++----- ...lass-string_zpp_specifier_strict_mode.phpt | 22 +++++++++---------- .../class-string_zpp_specifier_weak_mode.phpt | 9 ++++---- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 517c5894e1d0..dbc734cc54a0 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -485,27 +485,29 @@ ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, const zend_clas ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, uint32_t num, bool check_null) /* {{{ */ { - zend_class_entry *ce_base = *pce; + const zend_class_entry *ce_base = *pce; if (check_null && Z_TYPE_P(arg) == IS_NULL) { *pce = NULL; return 1; } - if (!try_convert_to_string(arg)) { + zend_string *class_name; + if (!zend_parse_arg_str(arg, &class_name, check_null, num)) { *pce = NULL; + zend_wrong_parameter_error(ZPP_ERROR_WRONG_ARG, num, NULL, check_null ? Z_EXPECTED_STRING_OR_NULL : Z_EXPECTED_STRING, arg); return 0; } - *pce = zend_lookup_class(Z_STR_P(arg)); + *pce = zend_lookup_class(class_name); if (ce_base) { if ((!*pce || !instanceof_function(*pce, ce_base))) { - zend_argument_type_error(num, "must be a class name derived from %s, %s given", ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg)); + zend_argument_type_error(num, "must be a class name derived from %s, %s given", ZSTR_VAL(ce_base->name), ZSTR_VAL(class_name)); *pce = NULL; return 0; } } if (!*pce) { - zend_argument_type_error(num, "must be a valid class name, %s given", Z_STRVAL_P(arg)); + zend_argument_type_error(num, "must be a valid class name, %s given", ZSTR_VAL(class_name)); return 0; } return 1; diff --git a/ext/zend_test/tests/zpp/class-string_zpp_specifier_strict_mode.phpt b/ext/zend_test/tests/zpp/class-string_zpp_specifier_strict_mode.phpt index 3dcd833ea16f..a72d504a2db3 100644 --- a/ext/zend_test/tests/zpp/class-string_zpp_specifier_strict_mode.phpt +++ b/ext/zend_test/tests/zpp/class-string_zpp_specifier_strict_mode.phpt @@ -36,16 +36,14 @@ foreach ($types as $type) { } ?> ---EXPECTF-- -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, given -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, given -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 1 given -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 42 given -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 73.5 given +--EXPECT-- +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, null given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, false given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, true given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, int given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, float given TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, string given - -Warning: Array to string conversion in %s on line %d -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, Array given -Error: Object of class stdClass could not be converted to string -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, S class given -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, Resource id #2 given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, array given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, stdClass given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, S given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, resource given diff --git a/ext/zend_test/tests/zpp/class-string_zpp_specifier_weak_mode.phpt b/ext/zend_test/tests/zpp/class-string_zpp_specifier_weak_mode.phpt index 3959fa07c94a..2110ecc4a0e4 100644 --- a/ext/zend_test/tests/zpp/class-string_zpp_specifier_weak_mode.phpt +++ b/ext/zend_test/tests/zpp/class-string_zpp_specifier_weak_mode.phpt @@ -35,15 +35,14 @@ foreach ($types as $type) { ?> --EXPECTF-- +Deprecated: zend_object_init_with_constructor(): Passing null to parameter #1 ($class) of type string is deprecated in %s on line %d TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, given TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, given TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 1 given TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 42 given TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, 73.5 given TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, string given - -Warning: Array to string conversion in %s on line %d -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, Array given -Error: Object of class stdClass could not be converted to string +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, array given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, stdClass given TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, S class given -TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be a valid class name, Resource id #2 given +TypeError: zend_object_init_with_constructor(): Argument #1 ($class) must be of type string, resource given