Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions Zend/tests/bug70914.phpt

This file was deleted.

2 changes: 1 addition & 1 deletion Zend/tests/get_class_vars/get_class_vars_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ array(2) {
["aa"]=>
int(4)
}
get_class_vars(): Argument #1 ($class) must be a valid class name, Unknown given
get_class_vars(): Argument #1 ($class) must be a valid class name, "Unknown" given
6 changes: 3 additions & 3 deletions Zend/tests/get_parent_class_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ bool(false)
string(3) "foo"
bool(false)
bool(false)
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, string given
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, string given
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, string given
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, "" given
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, "[[[[" given
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, " " given
bool(false)
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, array given
get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, int given
Expand Down
15 changes: 15 additions & 0 deletions Zend/tests/zpp/bug70914.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
Bug #70914 zend_throw_or_error() format string vulnerability
--EXTENSIONS--
zend_test
--FILE--
<?php

try {
var_dump(zend_class_name('%Z'));
} catch (TypeError $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
}
?>
--EXPECT--
TypeError: zend_class_name(): Argument #1 ($param) must be a valid class name, "%Z" given
192 changes: 92 additions & 100 deletions Zend/tests/zpp/class-string_zpp_specifier_strict_mode.phpt

Large diffs are not rendered by default.

196 changes: 92 additions & 104 deletions Zend/tests/zpp/class-string_zpp_specifier_weak_mode.phpt

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions Zend/tests/zpp/obj_or_class_name_zpp_strict_mode.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ Using 73.5:
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, float given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, float given
Using 'string':
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, string given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, string given
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, "string" given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, "string" given
Using '15':
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, string given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, string given
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, "15" given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, "15" given
Using '56.7':
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, string given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, string given
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, "56.7" given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, "56.7" given
Using 'stdClass':
string(8) "stdClass"
string(8) "stdClass"
Expand Down
12 changes: 6 additions & 6 deletions Zend/tests/zpp/obj_or_class_name_zpp_weak_mode.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ Using 73.5:
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, float given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, float given
Using 'string':
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, string given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, string given
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, "string" given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, "string" given
Using '15':
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, string given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, string given
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, "15" given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, "15" given
Using '56.7':
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, string given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, string given
TypeError: zend_obj_or_class_name(): Argument #1 ($param) must be an object or a valid class name, "56.7" given
TypeError: zend_obj_or_class_name_or_null(): Argument #1 ($param) must be an object, a valid class name, or null, "56.7" given
Using 'stdClass':
string(8) "stdClass"
string(8) "stdClass"
Expand Down
62 changes: 43 additions & 19 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,16 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t n
return;
}

if (Z_TYPE_P(arg) == IS_STRING && (
expected_type == Z_EXPECTED_CLASS_NAME ||
expected_type == Z_EXPECTED_CLASS_NAME_OR_NULL ||
expected_type == Z_EXPECTED_OBJECT_OR_CLASS_NAME ||
expected_type == Z_EXPECTED_OBJECT_OR_CLASS_NAME_OR_NULL
)) {
zend_argument_type_error(num, "must be %s, \"%s\" given", expected_error[expected_type], Z_STRVAL_P(arg));
return;
}

zend_argument_type_error(num, "must be %s, %s given", expected_error[expected_type], zend_zval_value_name(arg));
}
/* }}} */
Expand Down Expand Up @@ -492,23 +502,28 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **p
*pce = NULL;
return 1;
}
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;
/* Only accept string and Stringable(?) as int/foat/bool are not valid class names */
if (UNEXPECTED(Z_TYPE_P(arg) != IS_STRING)) {
if (Z_TYPE_P(arg) != IS_OBJECT || !zend_parse_arg_str_slow(arg, num)) {
*pce = NULL;
zend_wrong_parameter_type_error(num, check_null ? Z_EXPECTED_CLASS_NAME_OR_NULL : Z_EXPECTED_CLASS_NAME, arg);
return 0;
}
/* Object was converted to string */
ZEND_ASSERT(Z_TYPE_P(arg) == IS_STRING);
}
zend_string *class_name = 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), ZSTR_VAL(class_name));
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", ZSTR_VAL(class_name));
zend_wrong_parameter_type_error(num, check_null ? Z_EXPECTED_CLASS_NAME_OR_NULL : Z_EXPECTED_CLASS_NAME, arg);
return 0;
}
return 1;
Expand Down Expand Up @@ -1020,33 +1035,42 @@ static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec

case 'C':
{
zend_class_entry *lookup, **pce = va_arg(*va, zend_class_entry **);
zend_class_entry *ce_base = *pce;
zend_class_entry **pce = va_arg(*va, zend_class_entry **);
const zend_class_entry *ce_base = *pce;

if (check_null && Z_TYPE_P(arg) == IS_NULL) {
*pce = NULL;
break;
}
if (!try_convert_to_string(arg)) {
*pce = NULL;
return ""; /* try_convert_to_string() throws an exception */
}

if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
*pce = NULL;
} else {
*pce = lookup;
/* Only accept string and Stringable(?) as int/foat/bool are not valid class names */
if (UNEXPECTED(Z_TYPE_P(arg) != IS_STRING)) {
if (Z_TYPE_P(arg) != IS_OBJECT || !zend_parse_arg_str_slow(arg, arg_num)) {
*pce = NULL;
/* __toString may throw */
if (!EG(exception)) {
zend_spprintf(error, 0, "must be a valid class name%s, %s given",
check_null ? " or null" : "", zend_zval_value_name(arg));
}
*pce = NULL;
return "";
}
/* Object was converted to string */
ZEND_ASSERT(Z_TYPE_P(arg) == IS_STRING);
}
zend_string *class_name = Z_STR_P(arg);

*pce = zend_lookup_class(class_name);
if (ce_base) {
if ((!*pce || !instanceof_function(*pce, ce_base))) {
zend_spprintf(error, 0, "must be a class name derived from %s%s, %s given",
zend_spprintf(error, 0, "must be a class name derived from %s%s, \"%s\" given",
ZSTR_VAL(ce_base->name), check_null ? " or null" : "", Z_STRVAL_P(arg));
*pce = NULL;
return "";
}
}
if (!*pce) {
zend_spprintf(error, 0, "must be a valid class name%s, %s given",
zend_spprintf(error, 0, "must be a valid class name%s, \"%s\" given",
check_null ? " or null" : "", Z_STRVAL_P(arg));
return "";
}
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv)
_(Z_EXPECTED_ARRAY_OR_STRING_OR_NULL, "of type array|string|null") \
_(Z_EXPECTED_STRING_OR_LONG, "of type string|int") \
_(Z_EXPECTED_STRING_OR_LONG_OR_NULL, "of type string|int|null") \
_(Z_EXPECTED_CLASS_NAME, "a valid class name") \
_(Z_EXPECTED_CLASS_NAME_OR_NULL, "a valid class name or null") \
_(Z_EXPECTED_OBJECT_OR_CLASS_NAME, "an object or a valid class name") \
_(Z_EXPECTED_OBJECT_OR_CLASS_NAME_OR_NULL, "an object, a valid class name, or null") \
_(Z_EXPECTED_OBJECT_OR_STRING, "of type object|string") \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ $dom->registerNodeClass("Dom\\HTMLDocument", "DOMDocument");

?>
--EXPECTF--
Fatal error: Uncaught TypeError: DOMDocument::registerNodeClass(): Argument #1 ($baseClass) must be a class name derived from DOMNode, Dom\HTMLDocument given in %s:%d
Fatal error: Uncaught TypeError: DOMDocument::registerNodeClass(): Argument #1 ($baseClass) must be a class name derived from DOMNode, "Dom\HTMLDocument" given in %s:%d
Stack trace:
#0 %s(%d): DOMDocument->registerNodeClass('Dom\\HTMLDocumen...', 'DOMDocument')
#1 {main}
Expand Down
2 changes: 1 addition & 1 deletion ext/mysqli/tests/mysqli_fetch_object.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,5 @@ NULL
NULL
mysqli_result object is already closed
TypeError: mysqli_fetch_object(): Argument #3 ($constructor_args) must be of type array, string given
TypeError: mysqli_fetch_object(): Argument #2 ($class) must be a valid class name, this_class_does_not_exist given
TypeError: mysqli_fetch_object(): Argument #2 ($class) must be a valid class name, "this_class_does_not_exist" given
done!
2 changes: 1 addition & 1 deletion ext/mysqli/tests/mysqli_fetch_object_oo.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,5 @@ ArgumentCountError: Too few arguments to function mysqli_fetch_object_construct:
NULL
NULL
Error: mysqli_result object is already closed
TypeError: mysqli_result::fetch_object(): Argument #1 ($class) must be a valid class name, this_class_does_not_exist given
TypeError: mysqli_result::fetch_object(): Argument #1 ($class) must be a valid class name, "this_class_does_not_exist" given
done!
2 changes: 1 addition & 1 deletion ext/phar/tests/phar_oo_006.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ unlink(__DIR__ . '/files/phar_oo_006.phar.php');
__halt_compiler();
?>
--EXPECTF--
TypeError: SplFileInfo::setFileClass(): Argument #1 ($class) must be a class name derived from SplFileObject, SplFileInfo given
TypeError: SplFileInfo::setFileClass(): Argument #1 ($class) must be a class name derived from SplFileObject, "SplFileInfo" given
MyFile::__construct(phar://%s/a.php)
a.php
MyFile::__construct(phar://%s/b/c.php)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ try {
?>
--EXPECT--
Bad iterator type:
TypeError: ArrayObject::__construct(): Argument #3 ($iteratorClass) must be a class name derived from ArrayIterator, Exception given
TypeError: ArrayObject::__construct(): Argument #3 ($iteratorClass) must be a class name derived from ArrayIterator, "Exception" given
Non-existent class:
TypeError: ArrayObject::__construct(): Argument #3 ($iteratorClass) must be a class name derived from ArrayIterator, nonExistentClassName given
TypeError: ArrayObject::__construct(): Argument #3 ($iteratorClass) must be a class name derived from ArrayIterator, "nonExistentClassName" given
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ try {

?>
--EXPECT--
TypeError: ArrayObject::setIteratorClass(): Argument #1 ($iteratorClass) must be a class name derived from ArrayIterator, nonExistentClass given
TypeError: ArrayObject::setIteratorClass(): Argument #1 ($iteratorClass) must be a class name derived from ArrayIterator, stdClass given
TypeError: ArrayObject::__construct(): Argument #3 ($iteratorClass) must be a class name derived from ArrayIterator, nonExistentClass given
TypeError: ArrayObject::__construct(): Argument #3 ($iteratorClass) must be a class name derived from ArrayIterator, stdClass given
TypeError: ArrayObject::setIteratorClass(): Argument #1 ($iteratorClass) must be a class name derived from ArrayIterator, "nonExistentClass" given
TypeError: ArrayObject::setIteratorClass(): Argument #1 ($iteratorClass) must be a class name derived from ArrayIterator, "stdClass" given
TypeError: ArrayObject::__construct(): Argument #3 ($iteratorClass) must be a class name derived from ArrayIterator, "nonExistentClass" given
TypeError: ArrayObject::__construct(): Argument #3 ($iteratorClass) must be a class name derived from ArrayIterator, "stdClass" given
2 changes: 1 addition & 1 deletion ext/spl/tests/SplFileInfo_setFileClass_error.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ try {

?>
--EXPECT--
TypeError: SplFileInfo::setFileClass(): Argument #1 ($class) must be a class name derived from SplFileObject, stdClass given
TypeError: SplFileInfo::setFileClass(): Argument #1 ($class) must be a class name derived from SplFileObject, "stdClass" given
2 changes: 1 addition & 1 deletion ext/spl/tests/SplFileInfo_setInfoClass_error.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ try {

?>
--EXPECT--
TypeError: SplFileInfo::setInfoClass(): Argument #1 ($class) must be a class name derived from SplFileInfo, stdClass given
TypeError: SplFileInfo::setInfoClass(): Argument #1 ($class) must be a class name derived from SplFileInfo, "stdClass" given
2 changes: 1 addition & 1 deletion ext/spl/tests/bug80719.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ foreach ($array as $v) {

?>
--EXPECT--
TypeError: ArrayObject::setIteratorClass(): Argument #1 ($iteratorClass) must be a class name derived from ArrayIterator, FilterIterator given
TypeError: ArrayObject::setIteratorClass(): Argument #1 ($iteratorClass) must be a class name derived from ArrayIterator, "FilterIterator" given
int(42)
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ Argument is name of class which has no methods:
array(0) {
}
Argument is non existent class:
get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, string given
get_class_methods(): Argument #1 ($object_or_class) must be an object or a valid class name, "NonExistent" given
Done
Loading
Loading