Slightly clean up is_callable implementation

And adjust an error message to line up with the error message
used for $callable() in zend_execute.c.
This commit is contained in:
Nikita Popov 2021-09-02 10:29:15 +02:00
parent f3c5d1a568
commit 2ffa70b97c
8 changed files with 51 additions and 63 deletions

View File

@ -3727,63 +3727,51 @@ check_func:
case IS_ARRAY:
{
zval *method = NULL;
zval *obj = NULL;
if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
if (zend_hash_num_elements(Z_ARRVAL_P(callable)) != 2) {
if (error) *error = estrdup("array callback must have exactly two members");
return 0;
}
do {
if (obj == NULL || method == NULL) {
break;
zval *obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
zval *method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
if (!obj || !method) {
if (error) *error = estrdup("array callback has to contain indices 0 and 1");
return 0;
}
ZVAL_DEREF(obj);
if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
if (error) *error = estrdup("first array member is not a valid class name or object");
return 0;
}
ZVAL_DEREF(method);
if (Z_TYPE_P(method) != IS_STRING) {
if (error) *error = estrdup("second array member is not a valid method");
return 0;
}
if (Z_TYPE_P(obj) == IS_STRING) {
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
return 1;
}
ZVAL_DEREF(method);
if (Z_TYPE_P(method) != IS_STRING) {
break;
}
ZVAL_DEREF(obj);
if (Z_TYPE_P(obj) == IS_STRING) {
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
return 1;
}
if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error)) {
return 0;
}
} else if (Z_TYPE_P(obj) == IS_OBJECT) {
fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
fcc->object = Z_OBJ_P(obj);
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
fcc->called_scope = fcc->calling_scope;
return 1;
}
} else {
break;
}
callable = method;
goto check_func;
} while (0);
if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
if (!obj || (!Z_ISREF_P(obj)?
(Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) :
(Z_TYPE_P(Z_REFVAL_P(obj)) != IS_STRING && Z_TYPE_P(Z_REFVAL_P(obj)) != IS_OBJECT))) {
if (error) *error = estrdup("first array member is not a valid class name or object");
} else {
if (error) *error = estrdup("second array member is not a valid method");
if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error)) {
return 0;
}
} else {
if (error) *error = estrdup("array must have exactly two members");
ZEND_ASSERT(Z_TYPE_P(obj) == IS_OBJECT);
fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
fcc->object = Z_OBJ_P(obj);
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
fcc->called_scope = fcc->calling_scope;
return 1;
}
}
callable = method;
goto check_func;
}
return 0;
case IS_OBJECT:

View File

@ -45,5 +45,5 @@ try {
CallbackFilterIterator::__construct() expects exactly 2 arguments, 0 given
CallbackFilterIterator::__construct() expects exactly 2 arguments, 1 given
CallbackFilterIterator::__construct(): Argument #2 ($callback) must be a valid callback, no array or string given
CallbackFilterIterator::__construct(): Argument #2 ($callback) must be a valid callback, array must have exactly two members
CallbackFilterIterator::__construct(): Argument #2 ($callback) must be a valid callback, array callback must have exactly two members
some message

View File

@ -45,8 +45,8 @@ try {
*** Testing array_diff_uassoc() : error conditions ***
-- Testing array_diff_uassoc() function with more than expected no. of arguments --
array_diff_uassoc(): Argument #4 must be a valid callback, array must have exactly two members
array_diff_uassoc(): Argument #6 must be a valid callback, array must have exactly two members
array_diff_uassoc(): Argument #4 must be a valid callback, array callback must have exactly two members
array_diff_uassoc(): Argument #6 must be a valid callback, array callback must have exactly two members
-- Testing array_diff_uassoc() function with less than expected no. of arguments --
array_diff_uassoc(): Argument #2 must be a valid callback, array must have exactly two members
array_diff_uassoc(): Argument #2 must be a valid callback, array callback must have exactly two members

View File

@ -140,7 +140,7 @@ array_map(): Argument #1 ($callback) must be a valid callback or null, cannot ac
-- class without members --
EmptyClass
array_map(): Argument #1 ($callback) must be a valid callback or null, array must have exactly two members
array_map(): Argument #1 ($callback) must be a valid callback or null, array callback must have exactly two members
-- abstract class --
ChildClass::emptyFunction

View File

@ -120,5 +120,5 @@ array(2) {
-- with empty string --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "" not found or invalid function name
-- with empty array --
array_map(): Argument #1 ($callback) must be a valid callback or null, array must have exactly two members
array_map(): Argument #1 ($callback) must be a valid callback or null, array callback must have exactly two members
Done

View File

@ -121,7 +121,7 @@ array_map(): Argument #1 ($callback) must be a valid callback or null, function
array_map(): Argument #1 ($callback) must be a valid callback or null, function "" not found or invalid function name
-- Iteration 16 --
array_map(): Argument #1 ($callback) must be a valid callback or null, array must have exactly two members
array_map(): Argument #1 ($callback) must be a valid callback or null, array callback must have exactly two members
-- Iteration 17 --
array_map(): Argument #1 ($callback) must be a valid callback or null, first array member is not a valid class name or object

View File

@ -73,7 +73,7 @@ checkAndClean();
--EXPECTF--
---> Test arrays:
Warning: ob_start(): array must have exactly two members in %s on line %d
Warning: ob_start(): array callback must have exactly two members in %s on line %d
Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false)
@ -89,7 +89,7 @@ Array
(
)
Warning: ob_start(): array must have exactly two members in %s on line %d
Warning: ob_start(): array callback must have exactly two members in %s on line %d
Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false)
@ -97,7 +97,7 @@ Array
(
)
Warning: ob_start(): array must have exactly two members in %s on line %d
Warning: ob_start(): array callback must have exactly two members in %s on line %d
Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false)
@ -105,7 +105,7 @@ Array
(
)
Warning: ob_start(): array must have exactly two members in %s on line %d
Warning: ob_start(): array callback must have exactly two members in %s on line %d
Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false)
@ -125,7 +125,7 @@ Array
)
Warning: ob_start(): array must have exactly two members in %s on line %d
Warning: ob_start(): array callback must have exactly two members in %s on line %d
Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false)

View File

@ -14,7 +14,7 @@ var_dump(ob_start(array($c)));
echo "done"
?>
--EXPECTF--
Warning: ob_start(): array must have exactly two members in %s on line %d
Warning: ob_start(): array callback must have exactly two members in %s on line %d
Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false)