Skip to content

Commit bb0ab98

Browse files
committed
Zend: is_callable() wrongly accepts objects with no get_closure handler.
Fix #23121 zend_is_callable_at_frame() tested `get_closure && get_closure(...) == FAILURE`, so a NULL handler short circuited past the error branch into the success path, leaving fcc->function_handler NULL. zend_fcc_addref() then asserted and call_user_func() dereferenced the null zend_function. Close GH-23123
1 parent c4c76bf commit bb0ab98

3 files changed

Lines changed: 39 additions & 1 deletion

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ PHP NEWS
77
possible. (NickSdot)
88
. Fixed GH-23083 (SEGV build_trace_args in zend_exceptions.c with
99
-d error_include_args=On). (David Carlier)
10+
. Fixed GH-23121 (is_callable() wrongly accepts objects with no get_closure
11+
handler). (David Carlier)
1012

1113
- Curl:
1214
. Improved cURL option validation errors to include the option name.

Zend/tests/gh23121.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-23121 (Assertion failure in zend_fcc_addref() for an object whose class has no get_closure handler)
3+
--EXTENSIONS--
4+
simplexml
5+
--FILE--
6+
<?php
7+
$sxe = new SimpleXMLElement('<root/>');
8+
9+
var_dump(is_callable($sxe));
10+
11+
try {
12+
$sxe();
13+
} catch (Error $e) {
14+
echo $e->getMessage(), PHP_EOL;
15+
}
16+
17+
try {
18+
call_user_func($sxe);
19+
} catch (TypeError $e) {
20+
echo $e->getMessage(), PHP_EOL;
21+
}
22+
23+
try {
24+
libxml_set_external_entity_loader($sxe);
25+
} catch (TypeError $e) {
26+
echo $e->getMessage(), PHP_EOL;
27+
}
28+
29+
var_dump(libxml_get_external_entity_loader());
30+
?>
31+
--EXPECT--
32+
bool(false)
33+
Object of type SimpleXMLElement is not callable
34+
call_user_func(): Argument #1 ($callback) must be a valid callback, no array or string given
35+
libxml_set_external_entity_loader(): Argument #1 ($resolver_function) must be a valid callback or null, no array or string given
36+
NULL

Zend/zend_API.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4240,7 +4240,7 @@ ZEND_API bool zend_is_callable_at_frame(
42404240
}
42414241

42424242
case IS_OBJECT:
4243-
if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == FAILURE) {
4243+
if (!Z_OBJ_HANDLER_P(callable, get_closure) || Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == FAILURE) {
42444244
if (error) *error = estrdup("no array or string given");
42454245
return 0;
42464246
}

0 commit comments

Comments
 (0)