mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2026-01-26 21:41:34 +03:00
parser: Fix infinite loop in xmlCtxtParseContent
The loop to find an element/document ancestor uses "cur = node->parent"
as the iterator instead of "cur = cur->parent". This causes an infinite
loop when the immediate parent is not an element/document/html node
(e.g., when the node's parent is an entity reference).
Fix by iterating with cur->parent to properly walk up the ancestor chain.
Add regression test to testparser.c.
Fixes: 4f329dc5 ("parser: Implement xmlCtxtParseContent")
This commit is contained in:
committed by
Daniel Garcia Moreno
parent
f75abfcaa4
commit
4c3f00ba39
2
parser.c
2
parser.c
@@ -12033,7 +12033,7 @@ xmlCtxtParseContent(xmlParserCtxt *ctxt, xmlParserInput *input,
|
||||
case XML_ENTITY_REF_NODE:
|
||||
case XML_PI_NODE:
|
||||
case XML_COMMENT_NODE:
|
||||
for (cur = node->parent; cur != NULL; cur = node->parent) {
|
||||
for (cur = node->parent; cur != NULL; cur = cur->parent) {
|
||||
if ((cur->type == XML_ELEMENT_NODE) ||
|
||||
(cur->type == XML_DOCUMENT_NODE) ||
|
||||
(cur->type == XML_HTML_DOCUMENT_NODE)) {
|
||||
|
||||
44
testparser.c
44
testparser.c
@@ -399,6 +399,49 @@ testCtxtParseContent(void) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that xmlParseInNodeContext doesn't hang when called on a node
|
||||
* whose parent is an entity reference (not an element).
|
||||
* Regression test for infinite loop bug in xmlCtxtParseContent.
|
||||
*/
|
||||
static int
|
||||
testParseInNodeContextEntityParent(void) {
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr root, entRef, textNode, result = NULL;
|
||||
int err = 0;
|
||||
|
||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
root = xmlNewNode(NULL, BAD_CAST "root");
|
||||
xmlDocSetRootElement(doc, root);
|
||||
|
||||
/* Create an entity reference node */
|
||||
entRef = xmlNewReference(doc, BAD_CAST "testentity");
|
||||
xmlAddChild(root, entRef);
|
||||
|
||||
/* Create a text node as child of the entity reference */
|
||||
textNode = xmlNewText(BAD_CAST "content");
|
||||
xmlAddChild(entRef, textNode);
|
||||
|
||||
/*
|
||||
* This used to hang in an infinite loop because the code walked
|
||||
* up parents with "cur = node->parent" instead of "cur = cur->parent".
|
||||
*/
|
||||
xmlParseInNodeContext(textNode, "<x/>", 4, 0, &result);
|
||||
|
||||
if (result != NULL)
|
||||
xmlFreeNodeList(result);
|
||||
|
||||
/*
|
||||
* Entity reference children aren't freed automatically by xmlFreeDoc,
|
||||
* so we need to unlink and free the text node manually.
|
||||
*/
|
||||
xmlUnlinkNode(textNode);
|
||||
xmlFreeNode(textNode);
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
testNoBlanks(void) {
|
||||
const xmlChar xml[] =
|
||||
@@ -1504,6 +1547,7 @@ main(void) {
|
||||
#endif
|
||||
#ifdef LIBXML_OUTPUT_ENABLED
|
||||
err |= testCtxtParseContent();
|
||||
err |= testParseInNodeContextEntityParent();
|
||||
err |= testNoBlanks();
|
||||
err |= testSaveNullEnc();
|
||||
err |= testDocDumpFormatMemoryEnc();
|
||||
|
||||
Reference in New Issue
Block a user