153aa9179Sopenharmony_ciFrom 08f9d319ebe99f41f71336ea01767b9c652ef34f Mon Sep 17 00:00:00 2001
253aa9179Sopenharmony_ciFrom: Nick Wellnhofer <wellnhofer@aevum.de>
353aa9179Sopenharmony_ciDate: Thu, 16 Mar 2023 17:01:05 +0100
453aa9179Sopenharmony_ciSubject: [PATCH] valid: Make xmlValidateElement non-recursive
553aa9179Sopenharmony_ci
653aa9179Sopenharmony_ciFixes call stack overflows when validating deeply nested documents.
753aa9179Sopenharmony_ci
853aa9179Sopenharmony_ciFound by OSS-Fuzz.
953aa9179Sopenharmony_ci
1053aa9179Sopenharmony_ciReference:https://github.com/GNOME/libxml2/commit/08f9d319ebe99f41f71336ea01767b9c652ef34f
1153aa9179Sopenharmony_ciConflict:NA
1253aa9179Sopenharmony_ci
1353aa9179Sopenharmony_ci---
1453aa9179Sopenharmony_ci valid.c | 86 ++++++++++++++++++++++++++++-----------------------------
1553aa9179Sopenharmony_ci 1 file changed, 43 insertions(+), 43 deletions(-)
1653aa9179Sopenharmony_ci
1753aa9179Sopenharmony_cidiff --git a/valid.c b/valid.c
1853aa9179Sopenharmony_ciindex 9a2c708..3c0a869 100644
1953aa9179Sopenharmony_ci--- a/valid.c
2053aa9179Sopenharmony_ci+++ b/valid.c
2153aa9179Sopenharmony_ci@@ -6480,60 +6480,60 @@ name_ok:
2253aa9179Sopenharmony_ci  */
2353aa9179Sopenharmony_ci 
2453aa9179Sopenharmony_ci int
2553aa9179Sopenharmony_ci-xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem) {
2653aa9179Sopenharmony_ci-    xmlNodePtr child;
2753aa9179Sopenharmony_ci+xmlValidateElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr root) {
2853aa9179Sopenharmony_ci+    xmlNodePtr elem;
2953aa9179Sopenharmony_ci     xmlAttrPtr attr;
3053aa9179Sopenharmony_ci     xmlNsPtr ns;
3153aa9179Sopenharmony_ci     const xmlChar *value;
3253aa9179Sopenharmony_ci     int ret = 1;
3353aa9179Sopenharmony_ci 
3453aa9179Sopenharmony_ci-    if (elem == NULL) return(0);
3553aa9179Sopenharmony_ci-
3653aa9179Sopenharmony_ci-    /*
3753aa9179Sopenharmony_ci-     * XInclude elements were added after parsing in the infoset,
3853aa9179Sopenharmony_ci-     * they don't really mean anything validation wise.
3953aa9179Sopenharmony_ci-     */
4053aa9179Sopenharmony_ci-    if ((elem->type == XML_XINCLUDE_START) ||
4153aa9179Sopenharmony_ci-	(elem->type == XML_XINCLUDE_END) ||
4253aa9179Sopenharmony_ci-	(elem->type == XML_NAMESPACE_DECL))
4353aa9179Sopenharmony_ci-	return(1);
4453aa9179Sopenharmony_ci+    if (root == NULL) return(0);
4553aa9179Sopenharmony_ci 
4653aa9179Sopenharmony_ci     CHECK_DTD;
4753aa9179Sopenharmony_ci 
4853aa9179Sopenharmony_ci-    /*
4953aa9179Sopenharmony_ci-     * Entities references have to be handled separately
5053aa9179Sopenharmony_ci-     */
5153aa9179Sopenharmony_ci-    if (elem->type == XML_ENTITY_REF_NODE) {
5253aa9179Sopenharmony_ci-	return(1);
5353aa9179Sopenharmony_ci-    }
5453aa9179Sopenharmony_ci+    elem = root;
5553aa9179Sopenharmony_ci+    while (1) {
5653aa9179Sopenharmony_ci+        ret &= xmlValidateOneElement(ctxt, doc, elem);
5753aa9179Sopenharmony_ci+
5853aa9179Sopenharmony_ci+        if (elem->type == XML_ELEMENT_NODE) {
5953aa9179Sopenharmony_ci+            attr = elem->properties;
6053aa9179Sopenharmony_ci+            while (attr != NULL) {
6153aa9179Sopenharmony_ci+                value = xmlNodeListGetString(doc, attr->children, 0);
6253aa9179Sopenharmony_ci+                ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
6353aa9179Sopenharmony_ci+                if (value != NULL)
6453aa9179Sopenharmony_ci+                    xmlFree((char *)value);
6553aa9179Sopenharmony_ci+                attr= attr->next;
6653aa9179Sopenharmony_ci+            }
6753aa9179Sopenharmony_ci 
6853aa9179Sopenharmony_ci-    ret &= xmlValidateOneElement(ctxt, doc, elem);
6953aa9179Sopenharmony_ci-    if (elem->type == XML_ELEMENT_NODE) {
7053aa9179Sopenharmony_ci-	attr = elem->properties;
7153aa9179Sopenharmony_ci-	while (attr != NULL) {
7253aa9179Sopenharmony_ci-	    value = xmlNodeListGetString(doc, attr->children, 0);
7353aa9179Sopenharmony_ci-	    ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
7453aa9179Sopenharmony_ci-	    if (value != NULL)
7553aa9179Sopenharmony_ci-		xmlFree((char *)value);
7653aa9179Sopenharmony_ci-	    attr= attr->next;
7753aa9179Sopenharmony_ci-	}
7853aa9179Sopenharmony_ci-	ns = elem->nsDef;
7953aa9179Sopenharmony_ci-	while (ns != NULL) {
8053aa9179Sopenharmony_ci-	    if (elem->ns == NULL)
8153aa9179Sopenharmony_ci-		ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
8253aa9179Sopenharmony_ci-					       ns, ns->href);
8353aa9179Sopenharmony_ci-	    else
8453aa9179Sopenharmony_ci-		ret &= xmlValidateOneNamespace(ctxt, doc, elem,
8553aa9179Sopenharmony_ci-		                               elem->ns->prefix, ns, ns->href);
8653aa9179Sopenharmony_ci-	    ns = ns->next;
8753aa9179Sopenharmony_ci-	}
8853aa9179Sopenharmony_ci-    }
8953aa9179Sopenharmony_ci-    child = elem->children;
9053aa9179Sopenharmony_ci-    while (child != NULL) {
9153aa9179Sopenharmony_ci-        ret &= xmlValidateElement(ctxt, doc, child);
9253aa9179Sopenharmony_ci-        child = child->next;
9353aa9179Sopenharmony_ci+            ns = elem->nsDef;
9453aa9179Sopenharmony_ci+            while (ns != NULL) {
9553aa9179Sopenharmony_ci+                if (elem->ns == NULL)
9653aa9179Sopenharmony_ci+                    ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
9753aa9179Sopenharmony_ci+                                                   ns, ns->href);
9853aa9179Sopenharmony_ci+                else
9953aa9179Sopenharmony_ci+                    ret &= xmlValidateOneNamespace(ctxt, doc, elem,
10053aa9179Sopenharmony_ci+                                                   elem->ns->prefix, ns,
10153aa9179Sopenharmony_ci+                                                   ns->href);
10253aa9179Sopenharmony_ci+                ns = ns->next;
10353aa9179Sopenharmony_ci+            }
10453aa9179Sopenharmony_ci+
10553aa9179Sopenharmony_ci+            if (elem->children != NULL) {
10653aa9179Sopenharmony_ci+                elem = elem->children;
10753aa9179Sopenharmony_ci+                continue;
10853aa9179Sopenharmony_ci+            }
10953aa9179Sopenharmony_ci+        }
11053aa9179Sopenharmony_ci+
11153aa9179Sopenharmony_ci+        while (1) {
11253aa9179Sopenharmony_ci+            if (elem == root)
11353aa9179Sopenharmony_ci+                goto done;
11453aa9179Sopenharmony_ci+            if (elem->next != NULL)
11553aa9179Sopenharmony_ci+                break;
11653aa9179Sopenharmony_ci+            elem = elem->parent;
11753aa9179Sopenharmony_ci+        }
11853aa9179Sopenharmony_ci+        elem = elem->next;
11953aa9179Sopenharmony_ci     }
12053aa9179Sopenharmony_ci 
12153aa9179Sopenharmony_ci+done:
12253aa9179Sopenharmony_ci     return(ret);
12353aa9179Sopenharmony_ci }
12453aa9179Sopenharmony_ci 
12553aa9179Sopenharmony_ci-- 
12653aa9179Sopenharmony_ci2.27.0
12753aa9179Sopenharmony_ci
128