ext/xml: Deprecate xml_set_object() and passing non-callable strings as handlers (#15293)

This commit is contained in:
Gina Peter Banyard 2024-08-08 23:37:49 +01:00 committed by GitHub
parent 6eca7839af
commit 25b4696530
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 102 additions and 69 deletions

5
NEWS
View file

@ -55,6 +55,11 @@ PHP NEWS
. Implemented GH-15155 (Stream context is lost when custom stream wrapper is
being filtered). (Quentin Dreyer)
- XML:
. The xml_set_object() function has been deprecated. (Girgias)
. Passing non-callable strings to the xml_set_*_handler() functions is now
deprecated. (Girgias)
01 Aug 2024, PHP 8.4.0alpha4
- GMP:

View file

@ -189,7 +189,7 @@ PHP 8.4 UPGRADE NOTES
This means that xml_set_object() must now always be called prior to setting
method names as callables.
Passing an empty string to disable the handler is still allowed,
but not recommended.
but deprecated.
- XMLReader:
. Passing an invalid character encoding to XMLReader::open() or
@ -478,6 +478,13 @@ PHP 8.4 UPGRADE NOTES
. Unserializing strings using the uppercase 'S' tag is deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_4
- XML:
. The xml_set_object() function has been deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_4#xml_set_object_and_xml_set_handler_with_string_method_names
. Passing non-callable strings to the xml_set_*_handler() functions is now
deprecated.
RFC: https://wiki.php.net/rfc/deprecations_php_8_4#xml_set_object_and_xml_set_handler_with_string_method_names
========================================
5. Changed Functions
========================================

View file

@ -15,5 +15,6 @@ function boom()
}
boom();
?>
--EXPECT--
--EXPECTF--
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
ok

View file

@ -1,51 +0,0 @@
--TEST--
Bug #30266 (Invalid opcode 137/1/8)
--EXTENSIONS--
xml
--FILE--
<?php
/*
Currently (Feb 10, 2005) CVS HEAD fails with the following message:
Fatal error: Invalid opcode 137/1/8. in /home/hartmut/projects/php/dev/head/ext/xml/tests/bug30266.php on line 22
*/
class XML_Parser
{
public $dummy = "a";
function parse($data)
{
$parser = xml_parser_create();
xml_set_object($parser, $this);
xml_set_element_handler($parser, 'startHandler', 'endHandler');
xml_parse($parser, $data, true);
xml_parser_free($parser);
}
function startHandler($XmlParser, $tag, $attr)
{
$this->dummy = "b";
throw new Exception("ex");
}
function endHandler($XmlParser, $tag)
{
}
}
$p1 = new Xml_Parser();
try {
$p1->parse('<tag1><tag2></tag2></tag1>');
echo "Exception swallowed\n";
} catch (Exception $e) {
echo "OK\n";
}
?>
--EXPECT--
OK

View file

@ -100,8 +100,7 @@ HERE;
$parser = xml_parser_create(NULL);
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_object($parser, $this);
xml_set_element_handler($parser, "start_element", "end_element");
xml_set_element_handler($parser, $this->start_element(...), $this->end_element(...));
if ($this->chunk_size == 0) {
$success = @xml_parse($parser, $data, true);

View file

@ -31,5 +31,6 @@ $xml_parser->free();
?>
===DONE===
--EXPECT--
--EXPECTF--
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
===DONE===

View file

@ -59,7 +59,7 @@ xml_parse($parser, $xml, true);
xml_parser_free($parser);
?>
--EXPECT--
--EXPECTF--
Both handlers are trampolines:
Trampoline for start_handler
Tag: A
@ -75,6 +75,10 @@ Trampoline for end_handler
Tag: A
Start handler is trampoline, end handler method string:
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
Trampoline for start_handler
Tag: A
Trampoline for start_handler
@ -86,6 +90,10 @@ Method end handler: C
Method end handler: A
End handler is trampoline, start handler method string:
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
Method start handler: A
Method start handler: B
Trampoline for end_handler

View file

@ -48,7 +48,7 @@ try {
}
?>
--EXPECT--
--EXPECTF--
Invalid $parser:
TypeError: xml_set_processing_instruction_handler(): Argument #1 ($parser) must be of type XMLParser, stdClass given
Invalid callable type true:
@ -56,6 +56,12 @@ TypeError: xml_set_processing_instruction_handler(): Argument #2 ($handler) must
Invalid callable type int:
TypeError: xml_set_processing_instruction_handler(): Argument #2 ($handler) must be of type callable|string|null
String not callable and no object set:
Deprecated: xml_set_processing_instruction_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
ValueError: xml_set_processing_instruction_handler(): Argument #2 ($handler) an object must be set via xml_set_object() to be able to lookup method
String non existent method on set object:
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
Deprecated: xml_set_processing_instruction_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
ValueError: xml_set_processing_instruction_handler(): Argument #2 ($handler) method stdClass::nonexistent_method() does not exist

View file

@ -74,7 +74,7 @@ try {
}
?>
--EXPECT--
--EXPECTF--
Invalid $parser:
TypeError: xml_set_element_handler(): Argument #1 ($parser) must be of type XMLParser, stdClass given
Invalid start callable type true:
@ -86,10 +86,22 @@ TypeError: xml_set_element_handler(): Argument #2 ($start_handler) must be of ty
Invalid end callable type int:
TypeError: xml_set_element_handler(): Argument #3 ($end_handler) must be of type callable|string|null
Invalid start callable, no object set and string not callable:
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
ValueError: xml_set_element_handler(): Argument #2 ($start_handler) an object must be set via xml_set_object() to be able to lookup method
Invalid end callable, no object set and string not callable:
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
ValueError: xml_set_element_handler(): Argument #3 ($end_handler) an object must be set via xml_set_object() to be able to lookup method
Invalid start callable, string non existent method on set object:
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
ValueError: xml_set_element_handler(): Argument #2 ($start_handler) method stdClass::nonexistent_method() does not exist
Invalid end callable, string non existent method on set object:
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
ValueError: xml_set_element_handler(): Argument #3 ($end_handler) method stdClass::nonexistent_method() does not exist

View file

@ -29,9 +29,8 @@ class XML_Parser
function parse($data)
{
$parser = xml_parser_create();
xml_set_object($parser, $this);
xml_set_notation_decl_handler($parser, "notation_decl_handler");
xml_set_unparsed_entity_decl_handler($parser, "unparsed_entity_decl_handler");
xml_set_notation_decl_handler($parser, $this->notation_decl_handler(...));
xml_set_unparsed_entity_decl_handler($parser, $this->unparsed_entity_decl_handler(...));
xml_parse($parser, $data, true);
xml_parser_free($parser);
}

View file

@ -48,7 +48,12 @@ xml_parse($parser, <<<XML
XML);
?>
--EXPECT--
--EXPECTF--
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
A::start_element(CONTAINER)
B::start_element(CHILD)
end_handler(CHILD)

View file

@ -41,6 +41,11 @@ xml_parse($parser, <<<XML
XML);
?>
--EXPECT--
--EXPECTF--
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
Deprecated: xml_set_element_handler(): Passing non-callable strings is deprecated since 8.4 in %s on line %d
A::start_element(CONTAINER)
Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d
ValueError: xml_set_object(): Argument #2 ($object) cannot safely swap to object of class B as method "end_element" does not exist, which was set via xml_set_element_handler()

View file

@ -16,8 +16,7 @@ class XML_Parser
function parse($data)
{
$parser = xml_parser_create();
xml_set_object($parser, $this);
xml_set_processing_instruction_handler($parser, "PIHandler");
xml_set_processing_instruction_handler($parser, $this->PIHandler(...));
xml_parse($parser, $data, true);
xml_parser_free($parser);
}

View file

@ -23,6 +23,7 @@
#include "php.h"
#include "zend_variables.h"
#include "zend_attributes.h"
#include "ext/standard/info.h"
#include "ext/standard/html.h" /* For php_next_utf8_char() */
@ -1184,6 +1185,13 @@ PHP_FUNCTION(xml_set_element_handler)
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) {
parser = Z_XMLPARSER_P(pind);
php_error_docref(NULL, E_DEPRECATED, "Passing non-callable strings is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
zend_release_fcall_info_cache(&start_fcc);
zend_release_fcall_info_cache(&end_fcc);
RETURN_THROWS();
}
bool status = php_xml_check_string_method_arg(3, parser->object, end_method_name, &end_fcc);
if (status == false) {
zend_release_fcall_info_cache(&start_fcc);
@ -1193,6 +1201,13 @@ PHP_FUNCTION(xml_set_element_handler)
} 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) {
parser = Z_XMLPARSER_P(pind);
php_error_docref(NULL, E_DEPRECATED, "Passing non-callable strings is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
zend_release_fcall_info_cache(&start_fcc);
zend_release_fcall_info_cache(&end_fcc);
RETURN_THROWS();
}
bool status = php_xml_check_string_method_arg(2, parser->object, start_method_name, &start_fcc);
if (status == false) {
zend_release_fcall_info_cache(&start_fcc);
@ -1203,6 +1218,11 @@ PHP_FUNCTION(xml_set_element_handler)
zend_release_fcall_info_cache(&start_fcc);
zend_release_fcall_info_cache(&end_fcc);
php_error_docref(NULL, E_DEPRECATED, "Passing non-callable strings is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
parser = Z_XMLPARSER_P(pind);
bool status = php_xml_check_string_method_arg(2, parser->object, start_method_name, &start_fcc);
@ -1263,7 +1283,10 @@ static void php_xml_set_handler_parse_callable(
memcpy(parser_handler_fcc, &handler_fcc, sizeof(zend_fcall_info_cache));
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "OS", &pind, xml_parser_ce, &method_name) == SUCCESS) {
*parser = Z_XMLPARSER_P(pind);
php_error_docref(NULL, E_DEPRECATED, "Passing non-callable strings is deprecated since 8.4");
if (UNEXPECTED(EG(exception))) {
RETURN_THROWS();
}
bool status = php_xml_check_string_method_arg(2, (*parser)->object, method_name, parser_handler_fcc);
if (status == false) {
RETURN_THROWS();

View file

@ -149,6 +149,7 @@ function xml_parser_create(?string $encoding = null): XMLParser {}
function xml_parser_create_ns(?string $encoding = null, string $separator = ":"): XMLParser {}
#[\Deprecated(since: '8.4', message: 'provide a proper method callable to xml_set_*_handler() functions')]
function xml_set_object(XMLParser $parser, object $object): true {}
function xml_set_element_handler(XMLParser $parser, callable|string|null $start_handler, callable|string|null $end_handler): true {}

17
ext/xml/xml_arginfo.h generated
View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 69734dd8094fd69c878383d488900886d1162998 */
* Stub hash: 94b232499672dfd61c2c585a5d1d8a27d1a4a7ce */
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_xml_parser_create, 0, 0, XMLParser, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, encoding, IS_STRING, 1, "null")
@ -108,7 +108,7 @@ ZEND_FUNCTION(xml_parser_get_option);
static const zend_function_entry ext_functions[] = {
ZEND_FE(xml_parser_create, arginfo_xml_parser_create)
ZEND_FE(xml_parser_create_ns, arginfo_xml_parser_create_ns)
ZEND_FE(xml_set_object, arginfo_xml_set_object)
ZEND_RAW_FENTRY("xml_set_object", zif_xml_set_object, arginfo_xml_set_object, ZEND_ACC_DEPRECATED, NULL, NULL)
ZEND_FE(xml_set_element_handler, arginfo_xml_set_element_handler)
ZEND_FE(xml_set_character_data_handler, arginfo_xml_set_character_data_handler)
ZEND_FE(xml_set_processing_instruction_handler, arginfo_xml_set_processing_instruction_handler)
@ -165,6 +165,19 @@ static void register_xml_symbols(int module_number)
REGISTER_LONG_CONSTANT("XML_OPTION_SKIP_WHITE", PHP_XML_OPTION_SKIP_WHITE, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_OPTION_PARSE_HUGE", PHP_XML_OPTION_PARSE_HUGE, CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("XML_SAX_IMPL", PHP_XML_SAX_IMPL, CONST_PERSISTENT);
zend_attribute *attribute_Deprecated_func_xml_set_object_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "xml_set_object", sizeof("xml_set_object") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED), 2);
zval attribute_Deprecated_func_xml_set_object_0_arg0;
zend_string *attribute_Deprecated_func_xml_set_object_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1);
ZVAL_STR(&attribute_Deprecated_func_xml_set_object_0_arg0, attribute_Deprecated_func_xml_set_object_0_arg0_str);
ZVAL_COPY_VALUE(&attribute_Deprecated_func_xml_set_object_0->args[0].value, &attribute_Deprecated_func_xml_set_object_0_arg0);
attribute_Deprecated_func_xml_set_object_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE);
zval attribute_Deprecated_func_xml_set_object_0_arg1;
zend_string *attribute_Deprecated_func_xml_set_object_0_arg1_str = zend_string_init("provide a proper method callable to xml_set_*_handler() functions", strlen("provide a proper method callable to xml_set_*_handler() functions"), 1);
ZVAL_STR(&attribute_Deprecated_func_xml_set_object_0_arg1, attribute_Deprecated_func_xml_set_object_0_arg1_str);
ZVAL_COPY_VALUE(&attribute_Deprecated_func_xml_set_object_0->args[1].value, &attribute_Deprecated_func_xml_set_object_0_arg1);
attribute_Deprecated_func_xml_set_object_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE);
}
static zend_class_entry *register_class_XMLParser(void)