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,25 +3727,30 @@ check_func:
case IS_ARRAY: case IS_ARRAY:
{ {
zval *method = NULL; if (zend_hash_num_elements(Z_ARRVAL_P(callable)) != 2) {
zval *obj = NULL; if (error) *error = estrdup("array callback must have exactly two members");
return 0;
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);
} }
do { zval *obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
if (obj == NULL || method == NULL) { zval *method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
break; 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); ZVAL_DEREF(method);
if (Z_TYPE_P(method) != IS_STRING) { if (Z_TYPE_P(method) != IS_STRING) {
break; if (error) *error = estrdup("second array member is not a valid method");
return 0;
} }
ZVAL_DEREF(obj);
if (Z_TYPE_P(obj) == IS_STRING) { if (Z_TYPE_P(obj) == IS_STRING) {
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
return 1; return 1;
@ -3754,36 +3759,19 @@ check_func:
if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error)) { if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error)) {
return 0; return 0;
} }
} else {
} else if (Z_TYPE_P(obj) == IS_OBJECT) { ZEND_ASSERT(Z_TYPE_P(obj) == IS_OBJECT);
fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */ fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
fcc->object = Z_OBJ_P(obj); fcc->object = Z_OBJ_P(obj);
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) { if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
fcc->called_scope = fcc->calling_scope; fcc->called_scope = fcc->calling_scope;
return 1; return 1;
} }
} else {
break;
} }
callable = method; callable = method;
goto check_func; 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");
}
} else {
if (error) *error = estrdup("array must have exactly two members");
}
} }
return 0; return 0;
case IS_OBJECT: case IS_OBJECT:

View file

@ -45,5 +45,5 @@ try {
CallbackFilterIterator::__construct() expects exactly 2 arguments, 0 given CallbackFilterIterator::__construct() expects exactly 2 arguments, 0 given
CallbackFilterIterator::__construct() expects exactly 2 arguments, 1 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, 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 some message

View file

@ -45,8 +45,8 @@ try {
*** Testing array_diff_uassoc() : error conditions *** *** Testing array_diff_uassoc() : error conditions ***
-- Testing array_diff_uassoc() function with more than expected no. of arguments -- -- 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 #4 must be a valid callback, array callback 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 #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 -- -- 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 -- -- class without members --
EmptyClass 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 -- -- abstract class --
ChildClass::emptyFunction ChildClass::emptyFunction

View file

@ -120,5 +120,5 @@ array(2) {
-- with empty string -- -- with empty string --
array_map(): Argument #1 ($callback) must be a valid callback or null, function "" not found or invalid function name array_map(): Argument #1 ($callback) must be a valid callback or null, function "" not found or invalid function name
-- with empty array -- -- 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 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 array_map(): Argument #1 ($callback) must be a valid callback or null, function "" not found or invalid function name
-- Iteration 16 -- -- 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 -- -- 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 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-- --EXPECTF--
---> Test arrays: ---> 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 Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false) 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 Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false) 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 Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false) 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 Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false) 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 Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false) bool(false)

View file

@ -14,7 +14,7 @@ var_dump(ob_start(array($c)));
echo "done" echo "done"
?> ?>
--EXPECTF-- --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 Notice: ob_start(): Failed to create buffer in %s on line %d
bool(false) bool(false)