Skip to content

Commit edc99d5

Browse files
committed
Use new F ZPP type check
1 parent 7a68757 commit edc99d5

File tree

2 files changed

+84
-36
lines changed

2 files changed

+84
-36
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
--TEST--
2+
Test xml_set_element_handler handlers as trampoline callback
3+
--EXTENSIONS--
4+
xml
5+
--FILE--
6+
<?php
7+
8+
class TrampolineTest {
9+
public function __call(string $name, array $arguments) {
10+
echo 'Trampoline for ', $name, PHP_EOL;
11+
echo 'Tag: ', $arguments[1], PHP_EOL;
12+
}
13+
}
14+
15+
$o = new TrampolineTest();
16+
$startCallback = [$o, 'start_handler'];
17+
$endCallback = [$o, 'end_handler'];
18+
19+
$xml = <<<HERE
20+
<a>
21+
<b/>
22+
<c>Text</c>
23+
</a>
24+
HERE;
25+
26+
/*
27+
echo "1st arg is rubbish:\n";
28+
$rc = new ReflectionClass(XMLParser::class);
29+
$obj = $rc->newInstanceWithoutConstructor();
30+
31+
try {
32+
xml_set_element_handler($obj, $startCallback, $endCallback);
33+
} catch (\Throwable $e) {
34+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
35+
}
36+
*/
37+
$parser = xml_parser_create();
38+
/*
39+
try {
40+
xml_set_element_handler($parser, $startCallback, $endCallback);
41+
} catch (\Throwable $e) {
42+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
43+
}
44+
*/
45+
echo "2nd arg is rubbish:\n";
46+
try {
47+
xml_set_element_handler($parser, [], $endCallback);
48+
} catch (\Throwable $e) {
49+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
50+
}
51+
echo "3rd arg is rubbish:\n";
52+
try {
53+
xml_set_element_handler($parser, $startCallback, []);
54+
} catch (\Throwable $e) {
55+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
56+
}
57+
xml_parser_free($parser);
58+
59+
?>
60+
--EXPECT--
61+
2nd arg is rubbish:
62+
TypeError: xml_set_element_handler(): Argument #2 ($start_handler) must be of type callable|string|null
63+
3rd arg is rubbish:
64+
TypeError: xml_set_element_handler(): Argument #2 ($start_handler) must be of type callable|string|null

ext/xml/xml.c

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,49 +1157,35 @@ PHP_FUNCTION(xml_set_element_handler)
11571157
zend_string *start_method_name = NULL;
11581158
zend_string *end_method_name = NULL;
11591159

1160-
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "Of!f!", &pind, xml_parser_ce, &start_fci, &start_fcc, &end_fci, &end_fcc) == SUCCESS) {
1160+
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OF!F!", &pind, xml_parser_ce, &start_fci, &start_fcc, &end_fci, &end_fcc) == SUCCESS) {
11611161
parser = Z_XMLPARSER_P(pind);
1162-
if (ZEND_FCI_INITIALIZED(start_fci) && !ZEND_FCC_INITIALIZED(start_fcc)) {
1163-
zend_is_callable_ex(&start_fci.function_name, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &start_fcc, NULL);
1164-
/* Call trampoline has been cleared by zpp. Refetch it, because we want to deal
1165-
* with it ourselves. It is important that it is not refetched on every call,
1166-
* because calls may occur from different scopes. */
1167-
}
1168-
if (ZEND_FCI_INITIALIZED(end_fci) && !ZEND_FCC_INITIALIZED(end_fcc)) {
1169-
zend_is_callable_ex(&end_fci.function_name, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &end_fcc, NULL);
1170-
/* Call trampoline has been cleared by zpp. Refetch it, because we want to deal
1171-
* with it ourselves. It is important that it is not refetched on every call,
1172-
* because calls may occur from different scopes. */
1173-
}
1174-
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "Of!S", &pind, xml_parser_ce, &start_fci, &start_fcc, &end_method_name) == SUCCESS) {
1162+
goto set_handlers;
1163+
}
1164+
zend_release_fcall_info_cache(&start_fcc);
1165+
zend_release_fcall_info_cache(&end_fcc);
1166+
1167+
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OF!S", &pind, xml_parser_ce, &start_fci, &start_fcc, &end_method_name) == SUCCESS) {
11751168
parser = Z_XMLPARSER_P(pind);
11761169

11771170
bool status = php_xml_check_string_method_arg(3, parser->object, end_method_name, &end_fcc);
11781171
if (status == false) {
1172+
zend_release_fcall_info_cache(&start_fcc);
1173+
zend_release_fcall_info_cache(&end_fcc);
11791174
RETURN_THROWS();
11801175
}
1181-
1182-
if (ZEND_FCI_INITIALIZED(start_fci) && !ZEND_FCC_INITIALIZED(start_fcc)) {
1183-
zend_is_callable_ex(&start_fci.function_name, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &start_fcc, NULL);
1184-
/* Call trampoline has been cleared by zpp. Refetch it, because we want to deal
1185-
* with it ourselves. It is important that it is not refetched on every call,
1186-
* because calls may occur from different scopes. */
1187-
}
1188-
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OSf!", &pind, xml_parser_ce, &start_method_name, &end_fci, &end_fcc) == SUCCESS) {
1176+
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OSF!", &pind, xml_parser_ce, &start_method_name, &end_fci, &end_fcc) == SUCCESS) {
11891177
parser = Z_XMLPARSER_P(pind);
11901178

11911179
bool status = php_xml_check_string_method_arg(2, parser->object, start_method_name, &start_fcc);
11921180
if (status == false) {
1181+
zend_release_fcall_info_cache(&start_fcc);
1182+
zend_release_fcall_info_cache(&end_fcc);
11931183
RETURN_THROWS();
11941184
}
1195-
1196-
if (ZEND_FCI_INITIALIZED(end_fci) && !ZEND_FCC_INITIALIZED(end_fcc)) {
1197-
zend_is_callable_ex(&end_fci.function_name, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &end_fcc, NULL);
1198-
/* Call trampoline has been cleared by zpp. Refetch it, because we want to deal
1199-
* with it ourselves. It is important that it is not refetched on every call,
1200-
* because calls may occur from different scopes. */
1201-
}
12021185
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OSS", &pind, xml_parser_ce, &start_method_name, &end_method_name) == SUCCESS) {
1186+
zend_release_fcall_info_cache(&start_fcc);
1187+
zend_release_fcall_info_cache(&end_fcc);
1188+
12031189
parser = Z_XMLPARSER_P(pind);
12041190

12051191
bool status = php_xml_check_string_method_arg(2, parser->object, start_method_name, &start_fcc);
@@ -1213,6 +1199,9 @@ PHP_FUNCTION(xml_set_element_handler)
12131199
} else {
12141200
zval *dummy_start;
12151201
zval *dummy_end;
1202+
1203+
zend_release_fcall_info_cache(&start_fcc);
1204+
zend_release_fcall_info_cache(&end_fcc);
12161205
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ozz", &pind, xml_parser_ce, &dummy_start, &dummy_end) == FAILURE) {
12171206
RETURN_THROWS();
12181207
} else {
@@ -1229,6 +1218,7 @@ PHP_FUNCTION(xml_set_element_handler)
12291218
}
12301219
}
12311220

1221+
set_handlers:
12321222
xml_set_handler(&parser->startElementHandler, &start_fcc);
12331223
xml_set_handler(&parser->endElementHandler, &end_fcc);
12341224
XML_SetElementHandler(parser->parser, _xml_startElementHandler, _xml_endElementHandler);
@@ -1247,18 +1237,12 @@ static void php_xml_set_handler_parse_callable(
12471237
zend_fcall_info_cache handler_fcc = {0};
12481238
zend_string *method_name = NULL;
12491239

1250-
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "Of!", &pind, xml_parser_ce, &handler_fci, &handler_fcc) == SUCCESS) {
1240+
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OF!", &pind, xml_parser_ce, &handler_fci, &handler_fcc) == SUCCESS) {
12511241
*parser = Z_XMLPARSER_P(pind);
12521242
if (!ZEND_FCI_INITIALIZED(handler_fci)) {
12531243
/* Free handler, so just return and a uninitialized FCC communicates this */
12541244
return;
12551245
}
1256-
if (!ZEND_FCC_INITIALIZED(handler_fcc)) {
1257-
zend_is_callable_ex(&handler_fci.function_name, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &handler_fcc, NULL);
1258-
/* Call trampoline has been cleared by zpp. Refetch it, because we want to deal
1259-
* with it ourselves. It is important that it is not refetched on every call,
1260-
* because calls may occur from different scopes. */
1261-
}
12621246
memcpy(parser_handler_fcc, &handler_fcc, sizeof(zend_fcall_info_cache));
12631247
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OS", &pind, xml_parser_ce, &method_name) == SUCCESS) {
12641248
*parser = Z_XMLPARSER_P(pind);

0 commit comments

Comments
 (0)