diff --git a/NEWS b/NEWS index 4003a5cafe2ea..803c00a9fc64f 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,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: diff --git a/UPGRADING b/UPGRADING index 31fc8cae26250..2a1d6314e6954 100644 --- a/UPGRADING +++ b/UPGRADING @@ -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 @@ -474,6 +474,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 ======================================== diff --git a/Zend/tests/bug34617.phpt b/Zend/tests/bug34617.phpt index 9468c1111266d..a6f3ea8ca7f07 100644 --- a/Zend/tests/bug34617.phpt +++ b/Zend/tests/bug34617.phpt @@ -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 diff --git a/ext/xml/tests/bug30266.phpt b/ext/xml/tests/bug30266.phpt deleted file mode 100644 index 6f959e979c37b..0000000000000 --- a/ext/xml/tests/bug30266.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -Bug #30266 (Invalid opcode 137/1/8) ---EXTENSIONS-- -xml ---FILE-- -dummy = "b"; - throw new Exception("ex"); - } - - function endHandler($XmlParser, $tag) - { - } -} - -$p1 = new Xml_Parser(); -try { - $p1->parse(''); - echo "Exception swallowed\n"; -} catch (Exception $e) { - echo "OK\n"; -} -?> ---EXPECT-- -OK diff --git a/ext/xml/tests/bug32001.phpt b/ext/xml/tests/bug32001.phpt index 3f1600768d8b8..023f476edc697 100644 --- a/ext/xml/tests/bug32001.phpt +++ b/ext/xml/tests/bug32001.phpt @@ -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); diff --git a/ext/xml/tests/bug72793.phpt b/ext/xml/tests/bug72793.phpt index 57bc815d75fdb..b9e53eaf3a54a 100644 --- a/ext/xml/tests/bug72793.phpt +++ b/ext/xml/tests/bug72793.phpt @@ -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=== diff --git a/ext/xml/tests/set_element_handler_trampoline.phpt b/ext/xml/tests/set_element_handler_trampoline.phpt index c7137758ea7cb..884b6db219215 100644 --- a/ext/xml/tests/set_element_handler_trampoline.phpt +++ b/ext/xml/tests/set_element_handler_trampoline.phpt @@ -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 diff --git a/ext/xml/tests/set_handler_errors.phpt b/ext/xml/tests/set_handler_errors.phpt index bf8cb2a71f7cd..3cd6c4d590813 100644 --- a/ext/xml/tests/set_handler_errors.phpt +++ b/ext/xml/tests/set_handler_errors.phpt @@ -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 diff --git a/ext/xml/tests/xml_set_element_handler_errors.phpt b/ext/xml/tests/xml_set_element_handler_errors.phpt index e9424579aceb3..19a3e6a3d0734 100644 --- a/ext/xml/tests/xml_set_element_handler_errors.phpt +++ b/ext/xml/tests/xml_set_element_handler_errors.phpt @@ -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 diff --git a/ext/xml/tests/xml_set_notation_decl_handler_basic.phpt b/ext/xml/tests/xml_set_notation_decl_handler_basic.phpt index 8c76b20d1eca7..ff2530cfead79 100644 --- a/ext/xml/tests/xml_set_notation_decl_handler_basic.phpt +++ b/ext/xml/tests/xml_set_notation_decl_handler_basic.phpt @@ -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); } diff --git a/ext/xml/tests/xml_set_object_multiple_times.phpt b/ext/xml/tests/xml_set_object_multiple_times.phpt index 3be0e0a8ddee2..2c8fa14f6b928 100644 --- a/ext/xml/tests/xml_set_object_multiple_times.phpt +++ b/ext/xml/tests/xml_set_object_multiple_times.phpt @@ -48,7 +48,12 @@ xml_parse($parser, << ---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) diff --git a/ext/xml/tests/xml_set_object_multiple_times_errors.phpt b/ext/xml/tests/xml_set_object_multiple_times_errors.phpt index 85e8694dd79ec..2f52ec65e1b35 100644 --- a/ext/xml/tests/xml_set_object_multiple_times_errors.phpt +++ b/ext/xml/tests/xml_set_object_multiple_times_errors.phpt @@ -41,6 +41,11 @@ xml_parse($parser, << ---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() diff --git a/ext/xml/tests/xml_set_processing_instruction_handler_basic.phpt b/ext/xml/tests/xml_set_processing_instruction_handler_basic.phpt index d048e2950982e..6041b2d44ee12 100644 --- a/ext/xml/tests/xml_set_processing_instruction_handler_basic.phpt +++ b/ext/xml/tests/xml_set_processing_instruction_handler_basic.phpt @@ -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); } diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 1ae8d32c1f3fa..d1965b7bb53dc 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -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(); diff --git a/ext/xml/xml.stub.php b/ext/xml/xml.stub.php index 8b2bb9fd91ae7..54c286ff845c8 100644 --- a/ext/xml/xml.stub.php +++ b/ext/xml/xml.stub.php @@ -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 {} diff --git a/ext/xml/xml_arginfo.h b/ext/xml/xml_arginfo.h index 55c7d76b5497b..7b31981ed60da 100644 --- a/ext/xml/xml_arginfo.h +++ b/ext/xml/xml_arginfo.h @@ -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)