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)