libxml2/backport-valid-Make-xmlValidateElement-non-recursive.patch
zhuofeng feb7e8218d backport upstream patches
(cherry picked from commit ec64ed27a9add0f7a9bf6ee351ad67302a60c383)
2023-06-20 11:16:46 +08:00

128 lines
3.6 KiB
Diff

From 08f9d319ebe99f41f71336ea01767b9c652ef34f Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 16 Mar 2023 17:01:05 +0100
Subject: [PATCH] valid: Make xmlValidateElement non-recursive
Fixes call stack overflows when validating deeply nested documents.
Found by OSS-Fuzz.
Reference:https://github.com/GNOME/libxml2/commit/08f9d319ebe99f41f71336ea01767b9c652ef34f
Conflict:NA
---
valid.c | 86 ++++++++++++++++++++++++++++-----------------------------
1 file changed, 43 insertions(+), 43 deletions(-)
diff --git a/valid.c b/valid.c
index 9a2c708..3c0a869 100644
--- a/valid.c
+++ b/valid.c
@@ -6480,60 +6480,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);
- }
+ 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;
+ }
- 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;
+ 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);
}
--
2.27.0