Merge branch 'PHP-8.2' into PHP-8.3

* PHP-8.2:
  Fix memory leak when calling xml_parse_into_struct() twice
  Fix return type of stub of xml_parse_into_struct()
This commit is contained in:
Niels Dossche 2023-09-21 19:52:21 +02:00
commit 2bbe4fda75
5 changed files with 55 additions and 13 deletions

4
NEWS
View File

@ -35,6 +35,10 @@ PHP NEWS
foreach). (nielsdos)
. Fixed bug #55098 (SimpleXML iteration produces infinite loop). (nielsdos)
- XML:
. Fix return type of stub of xml_parse_into_struct(). (nielsdos)
. Fix memory leak when calling xml_parse_into_struct() twice. (nielsdos)
14 Sep 2023, PHP 8.3.0RC2
- Core:

View File

@ -0,0 +1,31 @@
--TEST--
GH-12254: xml_parse_into_struct() memory leak when called twice
--EXTENSIONS--
xml
--FILE--
<?php
$parser = xml_parser_create();
xml_set_element_handler($parser, function ($parser, $name, $attrs) {
echo "open\n";
var_dump($name, $attrs);
var_dump(xml_parse_into_struct($parser, "<container/>", $values, $tags));
}, function ($parser, $name) {
echo "close\n";
var_dump($name);
});
xml_parse_into_struct($parser, "<container/>", $values, $tags);
// Yes, this doesn't do anything but it at least shouldn't leak...
xml_parse_into_struct($parser, "<container/>", $values, $tags);
?>
--EXPECTF--
open
string(9) "CONTAINER"
array(0) {
}
Warning: xml_parse_into_struct(): Parser must not be called recursively in %s on line %d
bool(false)
close
string(9) "CONTAINER"

View File

@ -312,6 +312,16 @@ static zend_object *xml_parser_create_object(zend_class_entry *class_type) {
return &intern->std;
}
static void xml_parser_free_ltags(xml_parser *parser)
{
if (parser->ltags) {
int inx;
for (inx = 0; ((inx < parser->level) && (inx < XML_MAXLEVEL)); inx++)
efree(parser->ltags[ inx ]);
efree(parser->ltags);
}
}
static void xml_parser_free_obj(zend_object *object)
{
xml_parser *parser = xml_parser_from_obj(object);
@ -319,12 +329,7 @@ static void xml_parser_free_obj(zend_object *object)
if (parser->parser) {
XML_ParserFree(parser->parser);
}
if (parser->ltags) {
int inx;
for (inx = 0; ((inx < parser->level) && (inx < XML_MAXLEVEL)); inx++)
efree(parser->ltags[ inx ]);
efree(parser->ltags);
}
xml_parser_free_ltags(parser);
if (!Z_ISUNDEF(parser->startElementHandler)) {
zval_ptr_dtor(&parser->startElementHandler);
}
@ -1255,6 +1260,11 @@ PHP_FUNCTION(xml_parse_into_struct)
parser = Z_XMLPARSER_P(pind);
if (parser->isparsing) {
php_error_docref(NULL, E_WARNING, "Parser must not be called recursively");
RETURN_FALSE;
}
if (info) {
info = zend_try_array_init(info);
if (!info) {
@ -1274,15 +1284,12 @@ PHP_FUNCTION(xml_parse_into_struct)
}
parser->level = 0;
xml_parser_free_ltags(parser);
parser->ltags = safe_emalloc(XML_MAXLEVEL, sizeof(char *), 0);
XML_SetElementHandler(parser->parser, _xml_startElementHandler, _xml_endElementHandler);
XML_SetCharacterDataHandler(parser->parser, _xml_characterDataHandler);
if (parser->isparsing) {
php_error_docref(NULL, E_WARNING, "Parser must not be called recursively");
RETURN_FALSE;
}
parser->isparsing = 1;
ret = XML_Parse(parser->parser, (XML_Char*)data, data_len, 1);
parser->isparsing = 0;

View File

@ -182,7 +182,7 @@ function xml_parse(XMLParser $parser, string $data, bool $is_final = false): int
* @param array $values
* @param array $index
*/
function xml_parse_into_struct(XMLParser $parser, string $data, &$values, &$index = null): int {}
function xml_parse_into_struct(XMLParser $parser, string $data, &$values, &$index = null): int|false {}
function xml_get_error_code(XMLParser $parser): int {}

4
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: cd199a8733c51c8bb5970f86b7797ca91e6e59c6 */
* Stub hash: f87e295b35cd43db72a936ee5745297a45730090 */
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")
@ -46,7 +46,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xml_parse, 0, 2, IS_LONG, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, is_final, _IS_BOOL, 0, "false")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xml_parse_into_struct, 0, 3, IS_LONG, 0)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_xml_parse_into_struct, 0, 3, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_OBJ_INFO(0, parser, XMLParser, 0)
ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)
ZEND_ARG_INFO(1, values)