mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-19 14:50:07 +03:00
Make xmlDumpElementContent non-recursive
Avoid call stack overflow when dumping deeply nested element declarations. Found by OSS-Fuzz.
This commit is contained in:
parent
64966ebefd
commit
24e3973bc0
157
valid.c
157
valid.c
@ -1147,82 +1147,103 @@ xmlFreeElementContent(xmlElementContentPtr cur) {
|
||||
}
|
||||
|
||||
#ifdef LIBXML_OUTPUT_ENABLED
|
||||
/**
|
||||
* xmlDumpElementOccur:
|
||||
* @buf: An XML buffer
|
||||
* @cur: An element table
|
||||
*
|
||||
* Dump the occurence operator of an element.
|
||||
*/
|
||||
static void
|
||||
xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) {
|
||||
switch (cur->ocur) {
|
||||
case XML_ELEMENT_CONTENT_ONCE:
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_OPT:
|
||||
xmlBufferWriteChar(buf, "?");
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_MULT:
|
||||
xmlBufferWriteChar(buf, "*");
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_PLUS:
|
||||
xmlBufferWriteChar(buf, "+");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlDumpElementContent:
|
||||
* @buf: An XML buffer
|
||||
* @content: An element table
|
||||
* @glob: 1 if one must print the englobing parenthesis, 0 otherwise
|
||||
*
|
||||
* This will dump the content of the element table as an XML DTD definition
|
||||
*/
|
||||
static void
|
||||
xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content, int glob) {
|
||||
xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content) {
|
||||
xmlElementContentPtr cur;
|
||||
|
||||
if (content == NULL) return;
|
||||
|
||||
if (glob) xmlBufferWriteChar(buf, "(");
|
||||
switch (content->type) {
|
||||
case XML_ELEMENT_CONTENT_PCDATA:
|
||||
xmlBufferWriteChar(buf, "#PCDATA");
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_ELEMENT:
|
||||
if (content->prefix != NULL) {
|
||||
xmlBufferWriteCHAR(buf, content->prefix);
|
||||
xmlBufferWriteChar(buf, ":");
|
||||
}
|
||||
xmlBufferWriteCHAR(buf, content->name);
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_SEQ:
|
||||
if ((content->c1 != NULL) &&
|
||||
((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
|
||||
(content->c1->type == XML_ELEMENT_CONTENT_SEQ)))
|
||||
xmlDumpElementContent(buf, content->c1, 1);
|
||||
else
|
||||
xmlDumpElementContent(buf, content->c1, 0);
|
||||
xmlBufferWriteChar(buf, " , ");
|
||||
if ((content->c2 != NULL) &&
|
||||
((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
|
||||
((content->c2->type == XML_ELEMENT_CONTENT_SEQ) &&
|
||||
(content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))))
|
||||
xmlDumpElementContent(buf, content->c2, 1);
|
||||
else
|
||||
xmlDumpElementContent(buf, content->c2, 0);
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_OR:
|
||||
if ((content->c1 != NULL) &&
|
||||
((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
|
||||
(content->c1->type == XML_ELEMENT_CONTENT_SEQ)))
|
||||
xmlDumpElementContent(buf, content->c1, 1);
|
||||
else
|
||||
xmlDumpElementContent(buf, content->c1, 0);
|
||||
xmlBufferWriteChar(buf, " | ");
|
||||
if ((content->c2 != NULL) &&
|
||||
((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
|
||||
((content->c2->type == XML_ELEMENT_CONTENT_OR) &&
|
||||
(content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))))
|
||||
xmlDumpElementContent(buf, content->c2, 1);
|
||||
else
|
||||
xmlDumpElementContent(buf, content->c2, 0);
|
||||
break;
|
||||
default:
|
||||
xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
|
||||
"Internal: ELEMENT content corrupted invalid type\n",
|
||||
NULL);
|
||||
}
|
||||
if (glob)
|
||||
xmlBufferWriteChar(buf, ")");
|
||||
switch (content->ocur) {
|
||||
case XML_ELEMENT_CONTENT_ONCE:
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_OPT:
|
||||
xmlBufferWriteChar(buf, "?");
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_MULT:
|
||||
xmlBufferWriteChar(buf, "*");
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_PLUS:
|
||||
xmlBufferWriteChar(buf, "+");
|
||||
break;
|
||||
}
|
||||
xmlBufferWriteChar(buf, "(");
|
||||
cur = content;
|
||||
|
||||
do {
|
||||
if (cur == NULL) return;
|
||||
|
||||
switch (cur->type) {
|
||||
case XML_ELEMENT_CONTENT_PCDATA:
|
||||
xmlBufferWriteChar(buf, "#PCDATA");
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_ELEMENT:
|
||||
if (cur->prefix != NULL) {
|
||||
xmlBufferWriteCHAR(buf, cur->prefix);
|
||||
xmlBufferWriteChar(buf, ":");
|
||||
}
|
||||
xmlBufferWriteCHAR(buf, cur->name);
|
||||
break;
|
||||
case XML_ELEMENT_CONTENT_SEQ:
|
||||
case XML_ELEMENT_CONTENT_OR:
|
||||
if ((cur != content) &&
|
||||
(cur->parent != NULL) &&
|
||||
((cur->type != cur->parent->type) ||
|
||||
(cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
|
||||
xmlBufferWriteChar(buf, "(");
|
||||
cur = cur->c1;
|
||||
continue;
|
||||
default:
|
||||
xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
|
||||
"Internal: ELEMENT cur corrupted invalid type\n",
|
||||
NULL);
|
||||
}
|
||||
|
||||
while (cur != content) {
|
||||
xmlElementContentPtr parent = cur->parent;
|
||||
|
||||
if (parent == NULL) return;
|
||||
|
||||
if (((cur->type == XML_ELEMENT_CONTENT_OR) ||
|
||||
(cur->type == XML_ELEMENT_CONTENT_SEQ)) &&
|
||||
((cur->type != parent->type) ||
|
||||
(cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
|
||||
xmlBufferWriteChar(buf, ")");
|
||||
xmlDumpElementOccur(buf, cur);
|
||||
|
||||
if (cur == parent->c1) {
|
||||
if (parent->type == XML_ELEMENT_CONTENT_SEQ)
|
||||
xmlBufferWriteChar(buf, " , ");
|
||||
else if (parent->type == XML_ELEMENT_CONTENT_OR)
|
||||
xmlBufferWriteChar(buf, " | ");
|
||||
|
||||
cur = parent->c2;
|
||||
break;
|
||||
}
|
||||
|
||||
cur = parent;
|
||||
}
|
||||
} while (cur != content);
|
||||
|
||||
xmlBufferWriteChar(buf, ")");
|
||||
xmlDumpElementOccur(buf, content);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1703,7 +1724,7 @@ xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
|
||||
}
|
||||
xmlBufferWriteCHAR(buf, elem->name);
|
||||
xmlBufferWriteChar(buf, " ");
|
||||
xmlDumpElementContent(buf, elem->content, 1);
|
||||
xmlDumpElementContent(buf, elem->content);
|
||||
xmlBufferWriteChar(buf, ">\n");
|
||||
break;
|
||||
case XML_ELEMENT_TYPE_ELEMENT:
|
||||
@ -1714,7 +1735,7 @@ xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
|
||||
}
|
||||
xmlBufferWriteCHAR(buf, elem->name);
|
||||
xmlBufferWriteChar(buf, " ");
|
||||
xmlDumpElementContent(buf, elem->content, 1);
|
||||
xmlDumpElementContent(buf, elem->content);
|
||||
xmlBufferWriteChar(buf, ">\n");
|
||||
break;
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user