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:
parent
ca2bfecea9
commit
08f9d319eb
88
valid.c
88
valid.c
@ -6467,60 +6467,60 @@ 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);
|
||||
}
|
||||
|
||||
ret &= xmlValidateOneElement(ctxt, doc, elem);
|
||||
if (elem->type == XML_ELEMENT_NODE) {
|
||||
attr = elem->properties;
|
||||
while (attr != NULL) {
|
||||
value = xmlNodeListGetString(doc, attr->children, 0);
|
||||
ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
|
||||
if (value != NULL)
|
||||
xmlFree((char *)value);
|
||||
attr= attr->next;
|
||||
}
|
||||
ns = elem->nsDef;
|
||||
while (ns != NULL) {
|
||||
if (elem->ns == NULL)
|
||||
ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
|
||||
ns, ns->href);
|
||||
else
|
||||
ret &= xmlValidateOneNamespace(ctxt, doc, elem,
|
||||
elem->ns->prefix, ns, ns->href);
|
||||
ns = ns->next;
|
||||
}
|
||||
}
|
||||
child = elem->children;
|
||||
while (child != NULL) {
|
||||
ret &= xmlValidateElement(ctxt, doc, child);
|
||||
child = child->next;
|
||||
elem = root;
|
||||
while (1) {
|
||||
ret &= xmlValidateOneElement(ctxt, doc, elem);
|
||||
|
||||
if (elem->type == XML_ELEMENT_NODE) {
|
||||
attr = elem->properties;
|
||||
while (attr != NULL) {
|
||||
value = xmlNodeListGetString(doc, attr->children, 0);
|
||||
ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
|
||||
if (value != NULL)
|
||||
xmlFree((char *)value);
|
||||
attr= attr->next;
|
||||
}
|
||||
|
||||
ns = elem->nsDef;
|
||||
while (ns != NULL) {
|
||||
if (elem->ns == NULL)
|
||||
ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
|
||||
ns, ns->href);
|
||||
else
|
||||
ret &= xmlValidateOneNamespace(ctxt, doc, elem,
|
||||
elem->ns->prefix, ns,
|
||||
ns->href);
|
||||
ns = ns->next;
|
||||
}
|
||||
|
||||
if (elem->children != NULL) {
|
||||
elem = elem->children;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (elem == root)
|
||||
goto done;
|
||||
if (elem->next != NULL)
|
||||
break;
|
||||
elem = elem->parent;
|
||||
}
|
||||
elem = elem->next;
|
||||
}
|
||||
|
||||
done:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user