[libxml2] Fix a couple of problems in the parser



commit 489f9671e71cc44a97b23111b3126ac8a1e21a59
Author: Daniel Veillard <veillard redhat com>
Date:   Mon Aug 10 16:49:30 2009 +0200

    Fix a couple of problems in the parser
    
    * parser.c: a couple of nasty bugs CVE-2009-2414 and CVE-2009-2416

 parser.c |   79 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 67 insertions(+), 12 deletions(-)
---
diff --git a/parser.c b/parser.c
index a476060..bd2be67 100644
--- a/parser.c
+++ b/parser.c
@@ -5323,7 +5323,8 @@ xmlParseNotationType(xmlParserCtxtPtr ctxt) {
 	if (name == NULL) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
 			   "Name expected in NOTATION declaration\n");
-	    return(ret);
+            xmlFreeEnumeration(ret);
+	    return(NULL);
 	}
 	tmp = ret;
 	while (tmp != NULL) {
@@ -5339,7 +5340,10 @@ xmlParseNotationType(xmlParserCtxtPtr ctxt) {
 	}
 	if (tmp == NULL) {
 	    cur = xmlCreateEnumeration(name);
-	    if (cur == NULL) return(ret);
+	    if (cur == NULL) {
+                xmlFreeEnumeration(ret);
+                return(NULL);
+            }
 	    if (last == NULL) ret = last = cur;
 	    else {
 		last->next = cur;
@@ -5350,9 +5354,8 @@ xmlParseNotationType(xmlParserCtxtPtr ctxt) {
     } while (RAW == '|');
     if (RAW != ')') {
 	xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
-	if ((last != NULL) && (last != ret))
-	    xmlFreeEnumeration(last);
-	return(ret);
+        xmlFreeEnumeration(ret);
+	return(NULL);
     }
     NEXT;
     return(ret);
@@ -5407,7 +5410,10 @@ xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
 	    cur = xmlCreateEnumeration(name);
 	    if (!xmlDictOwns(ctxt->dict, name))
 		xmlFree(name);
-	    if (cur == NULL) return(ret);
+	    if (cur == NULL) {
+                xmlFreeEnumeration(ret);
+                return(NULL);
+            }
 	    if (last == NULL) ret = last = cur;
 	    else {
 		last->next = cur;
@@ -5775,9 +5781,10 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
 }
 
 /**
- * xmlParseElementChildrenContentDecl:
+ * xmlParseElementChildrenContentDeclPriv:
  * @ctxt:  an XML parser context
  * @inputchk:  the input used for the current entity, needed for boundary checks
+ * @depth: the level of recursion
  *
  * parse the declaration for a Mixed Element content
  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
@@ -5805,12 +5812,20 @@ xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
  * Returns the tree of xmlElementContentPtr describing the element 
  *          hierarchy.
  */
-xmlElementContentPtr
-xmlParseElementChildrenContentDecl (xmlParserCtxtPtr ctxt, int inputchk) {
+static xmlElementContentPtr
+xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
+                                       int depth) {
     xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
     const xmlChar *elem;
     xmlChar type = 0;
 
+    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
+        (depth >  2048)) {
+        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
+"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
+                          depth);
+	return(NULL);
+    }
     SKIP_BLANKS;
     GROW;
     if (RAW == '(') {
@@ -5819,7 +5834,8 @@ xmlParseElementChildrenContentDecl (xmlParserCtxtPtr ctxt, int inputchk) {
         /* Recurse on first child */
 	NEXT;
 	SKIP_BLANKS;
-        cur = ret = xmlParseElementChildrenContentDecl(ctxt, inputid);
+        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
+                                                           depth + 1);
 	SKIP_BLANKS;
 	GROW;
     } else {
@@ -5951,7 +5967,8 @@ xmlParseElementChildrenContentDecl (xmlParserCtxtPtr ctxt, int inputchk) {
 	    /* Recurse on second child */
 	    NEXT;
 	    SKIP_BLANKS;
-	    last = xmlParseElementChildrenContentDecl(ctxt, inputid);
+	    last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
+                                                          depth + 1);
 	    SKIP_BLANKS;
 	} else {
 	    elem = xmlParseName(ctxt);
@@ -6062,6 +6079,44 @@ xmlParseElementChildrenContentDecl (xmlParserCtxtPtr ctxt, int inputchk) {
 }
 
 /**
+ *
+ * xmlParseElementChildrenContentDecl:
+ * @ctxt:  an XML parser context
+ * @inputchk:  the input used for the current entity, needed for boundary checks
+ * @depth: the level of recursion
+ *
+ * parse the declaration for a Mixed Element content
+ * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
+ *
+ * [47] children ::= (choice | seq) ('?' | '*' | '+')?
+ *
+ * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
+ *
+ * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
+ *
+ * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
+ *
+ * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
+ * TODO Parameter-entity replacement text must be properly nested
+ *	with parenthesized groups. That is to say, if either of the
+ *	opening or closing parentheses in a choice, seq, or Mixed
+ *	construct is contained in the replacement text for a parameter
+ *	entity, both must be contained in the same replacement text. For
+ *	interoperability, if a parameter-entity reference appears in a
+ *	choice, seq, or Mixed construct, its replacement text should not
+ *	be empty, and neither the first nor last non-blank character of
+ *	the replacement text should be a connector (| or ,).
+ *
+ * Returns the tree of xmlElementContentPtr describing the element
+ *          hierarchy.
+ */
+xmlElementContentPtr
+xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
+    /* stub left for API/ABI compat */
+    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
+}
+
+/**
  * xmlParseElementContentDecl:
  * @ctxt:  an XML parser context
  * @name:  the name of the element being defined.
@@ -6097,7 +6152,7 @@ xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
         tree = xmlParseElementMixedContentDecl(ctxt, inputid);
 	res = XML_ELEMENT_TYPE_MIXED;
     } else {
-        tree = xmlParseElementChildrenContentDecl(ctxt, inputid);
+        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
 	res = XML_ELEMENT_TYPE_ELEMENT;
     }
     SKIP_BLANKS;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]