Blob Blame History Raw
Author: Alastair McKinstry <mckinstry@debian.org>
Description: Fix for recursion errors:
 CVE-2016-4570 Recursion using mxmlDelete at mxml-node.c:217 (stack-exhaustion-1.xml)
 CVE-2016-4571 	Recursion using mxml_write_node at mxml-file.c:2739 (stack-exhaustion-2.xml
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=825855
Last-Updated: 2016-06-10
Forwarded: yes 

Index: mxml-2.9/mxml-node.c
===================================================================
--- mxml-2.9.orig/mxml-node.c
+++ mxml-2.9/mxml-node.c
@@ -21,7 +21,7 @@
 #include "config.h"
 #include "mxml.h"
 
-
+#include "mxml-private.h"
 /*
  * Local functions...
  */
@@ -174,12 +174,12 @@ mxmlAdd(mxml_node_t *parent,		/* I - Par
  * node from its parent using the mxmlRemove() function.
  */
 
-void
-mxmlDelete(mxml_node_t *node)		/* I - Node to delete */
+
+static void
+mxmlDeleteLimited(mxml_node_t *node, int max_depth)		/* I - Node to delete */
 {
   int	i;				/* Looping var */
-
-
+  
 #ifdef DEBUG
   fprintf(stderr, "mxmlDelete(node=%p)\n", node);
 #endif /* DEBUG */
@@ -201,9 +201,15 @@ mxmlDelete(mxml_node_t *node)		/* I - No
   * Delete children...
   */
 
-  while (node->child)
-    mxmlDelete(node->child);
-
+  while (node->child) {
+    if (max_depth <= 0) {
+      mxml_error("Maximum recursion depth reached");
+      return;
+    } else {
+      mxmlDeleteLimited(node->child, max_depth-1);
+    }
+  }
+  
  /*
   * Now delete any node data...
   */
@@ -257,6 +263,11 @@ mxmlDelete(mxml_node_t *node)		/* I - No
   free(node);
 }
 
+void
+mxmlDelete(mxml_node_t *node)             /* I - Node to delete */
+{
+  mxmlDeleteLimited(node, MAX_DEPTH);
+}
 
 /*
  * 'mxmlGetRefCount()' - Get the current reference (use) count for a node.
Index: mxml-2.9/mxml-file.c
===================================================================
--- mxml-2.9.orig/mxml-file.c
+++ mxml-2.9/mxml-file.c
@@ -90,7 +90,8 @@ static int		mxml_write_name(const char *
 static int		mxml_write_node(mxml_node_t *node, void *p,
 			                mxml_save_cb_t cb, int col,
 					_mxml_putc_cb_t putc_cb,
-					_mxml_global_t *global);
+					_mxml_global_t *global,
+					int max_depth);
 static int		mxml_write_string(const char *s, void *p,
 					  _mxml_putc_cb_t putc_cb);
 static int		mxml_write_ws(mxml_node_t *node, void *p,
@@ -290,7 +291,7 @@ mxmlSaveFd(mxml_node_t    *node,	/* I -
   * Write the node...
   */
 
-  if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc, global)) < 0)
+  if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc, global,MAX_DEPTH)) < 0)
     return (-1);
 
   if (col > 0)
@@ -329,7 +330,7 @@ mxmlSaveFile(mxml_node_t    *node,	/* I
   * Write the node...
   */
 
-  if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc, global)) < 0)
+  if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc, global, MAX_DEPTH)) < 0)
     return (-1);
 
   if (col > 0)
@@ -377,7 +378,7 @@ mxmlSaveString(mxml_node_t    *node,	/*
   ptr[0] = buffer;
   ptr[1] = buffer + bufsize;
 
-  if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc, global)) < 0)
+  if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc, global, MAX_DEPTH)) < 0)
     return (-1);
 
   if (col > 0)
@@ -2708,7 +2709,8 @@ mxml_write_node(mxml_node_t     *node,	/
 	        mxml_save_cb_t  cb,	/* I - Whitespace callback */
 		int             col,	/* I - Current column */
 		_mxml_putc_cb_t putc_cb,/* I - Output callback */
-		_mxml_global_t  *global)/* I - Global data */
+		_mxml_global_t  *global,/* I - Global data */
+		int             max_depth)/*I - recursion limit */
 {
   int		i,			/* Looping var */
 		width;			/* Width of attr + value */
@@ -2808,7 +2810,11 @@ mxml_write_node(mxml_node_t     *node,	/
 
           for (child = node->child; child; child = child->next)
 	  {
-	    if ((col = mxml_write_node(child, p, cb, col, putc_cb, global)) < 0)
+	    if (max_depth <= 0) {
+	      mxml_error("Recursion limit reached");
+	      return (-1);
+	    }
+	    if ((col = mxml_write_node(child, p, cb, col, putc_cb, global, max_depth-1)) < 0)
 	      return (-1);
 	  }
 
Index: mxml-2.9/mxml-private.h
===================================================================
--- mxml-2.9.orig/mxml-private.h
+++ mxml-2.9/mxml-private.h
@@ -22,6 +22,8 @@
 #include "mxml.h"
 
 
+#define MAX_DEPTH   1000 /* Max. recursion depth */
+
 /*
  * Global, per-thread data...
  */