1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-12-25 23:21:26 +03:00

valid: Make xmlValidateElement non-recursive

Fixes call stack overflows when validating deeply nested documents.

Found by OSS-Fuzz.
This commit is contained in:
Nick Wellnhofer 2023-03-16 17:01:05 +01:00
parent ca2bfecea9
commit 08f9d319eb

48
valid.c
View File

@ -6467,34 +6467,21 @@ name_ok:
*/
int
xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) {
xmlNodePtr child;
xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) {
xmlNodePtr elem;
xmlAttrPtr attr;
xmlNsPtr ns;
const xmlChar *value;
int ret = 1;
if (elem == NULL) return(0);
/*
* XInclude elements were added after parsing in the infoset,
* they don't really mean anything validation wise.
*/
if ((elem->type == XML_XINCLUDE_START) ||
(elem->type == XML_XINCLUDE_END) ||
(elem->type == XML_NAMESPACE_DECL))
return(1);
if (root == NULL) return(0);
CHECK_DTD;
/*
* Entities references have to be handled separately
*/
if (elem->type == XML_ENTITY_REF_NODE) {
return(1);
}
elem = root;
while (1) {
ret &= xmlValidateOneElement(ctxt, doc, elem);
if (elem->type == XML_ELEMENT_NODE) {
attr = elem->properties;
while (attr != NULL) {
@ -6504,6 +6491,7 @@ xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) {
xmlFree((char *)value);
attr= attr->next;
}
ns = elem->nsDef;
while (ns != NULL) {
if (elem->ns == NULL)
@ -6511,16 +6499,28 @@ xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) {
ns, ns->href);
else
ret &= xmlValidateOneNamespace(ctxt, doc, elem,
elem->ns->prefix, ns, ns->href);
elem->ns->prefix, ns,
ns->href);
ns = ns->next;
}
if (elem->children != NULL) {
elem = elem->children;
continue;
}
child = elem->children;
while (child != NULL) {
ret &= xmlValidateElement(ctxt, doc, child);
child = child->next;
}
while (1) {
if (elem == root)
goto done;
if (elem->next != NULL)
break;
elem = elem->parent;
}
elem = elem->next;
}
done:
return(ret);
}