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...
*/