Package: libxslt1.1
Version: 1.1.23-1
Severity: grave
Tags: security, patch
Justification: user security hole

Hi

The following CVE(0) has been issued against libxslt.

CVE-2008-1767:

Buffer overflow in pattern.c in libxslt before 1.1.24 allows
context-dependent attackers to cause a denial of service (crash) and
possibly execute arbitrary code via an XSL style sheet file with a long
XSLT "transformation match" condition that triggers a large number of
steps.

Upstream patch is attached.

Please mention the CVE id in your changelog, when you fix this bug.

Cheers
Steffen

(0): http://nvd.nist.gov/nvd.cfm?cvename=CVE-2008-1767
Index: libxslt/pattern.c
===================================================================
--- libxslt/pattern.c	(revision 1465)
+++ libxslt-1.1.23/libxslt/pattern.c	(working copy)
@@ -106,7 +106,7 @@ struct _xsltCompMatch {
     int maxStep;
     xmlNsPtr *nsList;		/* the namespaces in scope */
     int nsNr;			/* the number of namespaces in scope */
-    xsltStepOp steps[40];        /* ops for computation */
+    xsltStepOpPtr steps;        /* ops for computation */
 };
 
 typedef struct _xsltParserContext xsltParserContext;
@@ -146,7 +146,16 @@ xsltNewCompMatch(void) {
 	return(NULL);
     }
     memset(cur, 0, sizeof(xsltCompMatch));
-    cur->maxStep = 40;
+    cur->maxStep = 10;
+    cur->nbStep = 0;
+    cur-> steps = (xsltStepOpPtr) xmlMalloc(sizeof(xsltStepOp) *
+                                            cur->maxStep);
+    if (cur->steps == NULL) {
+	xsltTransformError(NULL, NULL, NULL,
+		"xsltNewCompMatch : out of memory error\n");
+	xmlFree(cur);
+	return(NULL);
+    }
     cur->nsNr = 0;
     cur->nsList = NULL;
     cur->direct = 0;
@@ -181,6 +190,7 @@ xsltFreeCompMatch(xsltCompMatchPtr comp)
 	if (op->comp != NULL)
 	    xmlXPathFreeCompExpr(op->comp);
     }
+    xmlFree(comp->steps);
     memset(comp, -1, sizeof(xsltCompMatch));
     xmlFree(comp);
 }
@@ -279,14 +289,26 @@ static int
 xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp,
                  xsltOp op, xmlChar * value, xmlChar * value2, int novar)
 {
-    if (comp->nbStep >= 40) {
-        xsltTransformError(NULL, NULL, NULL,
-                         "xsltCompMatchAdd: overflow\n");
-        return (-1);
+    if (comp->nbStep >= comp->maxStep) {
+        xsltStepOpPtr tmp;
+
+	tmp = (xsltStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
+	                                 sizeof(xsltStepOp));
+	if (tmp == NULL) {
+	    xsltGenericError(xsltGenericErrorContext,
+	     "xsltCompMatchAdd: memory re-allocation failure.\n");
+	    if (ctxt->style != NULL)
+		ctxt->style->errors++;
+	    return (-1);
+	}
+        comp->maxStep *= 2;
+	comp->steps = tmp;
     }
     comp->steps[comp->nbStep].op = op;
     comp->steps[comp->nbStep].value = value;
     comp->steps[comp->nbStep].value2 = value2;
+    comp->steps[comp->nbStep].value3 = NULL;
+    comp->steps[comp->nbStep].comp = NULL;
     if (ctxt->ctxt != NULL) {
 	comp->steps[comp->nbStep].previousExtra =
 	    xsltAllocateExtraCtxt(ctxt->ctxt);
@@ -343,6 +365,7 @@ xsltSwapTopCompMatch(xsltCompMatchPtr co
 	register xmlChar *tmp;
 	register xsltOp op;
 	register xmlXPathCompExprPtr expr; 
+	register int t;
 	i = j - 1;
 	tmp = comp->steps[i].value;
 	comp->steps[i].value = comp->steps[j].value;
@@ -350,46 +373,74 @@ xsltSwapTopCompMatch(xsltCompMatchPtr co
 	tmp = comp->steps[i].value2;
 	comp->steps[i].value2 = comp->steps[j].value2;
 	comp->steps[j].value2 = tmp;
+	tmp = comp->steps[i].value3;
+	comp->steps[i].value3 = comp->steps[j].value3;
+	comp->steps[j].value3 = tmp;
 	op = comp->steps[i].op;
 	comp->steps[i].op = comp->steps[j].op;
 	comp->steps[j].op = op;
 	expr = comp->steps[i].comp;
 	comp->steps[i].comp = comp->steps[j].comp;
 	comp->steps[j].comp = expr;
+	t = comp->steps[i].previousExtra;
+	comp->steps[i].previousExtra = comp->steps[j].previousExtra;
+	comp->steps[j].previousExtra = t;
+	t = comp->steps[i].indexExtra;
+	comp->steps[i].indexExtra = comp->steps[j].indexExtra;
+	comp->steps[j].indexExtra = t;
+	t = comp->steps[i].lenExtra;
+	comp->steps[i].lenExtra = comp->steps[j].lenExtra;
+	comp->steps[j].lenExtra = t;
     }
 }
 
 /**
  * xsltReverseCompMatch:
+ * @ctxt: the parser context
  * @comp:  the compiled match expression
  *
  * reverse all the stack of expressions
  */
 static void
-xsltReverseCompMatch(xsltCompMatchPtr comp) {
+xsltReverseCompMatch(xsltParserContextPtr ctxt, xsltCompMatchPtr comp) {
     int i = 0;
     int j = comp->nbStep - 1;
 
     while (j > i) {
 	register xmlChar *tmp;
 	register xsltOp op;
-	register xmlXPathCompExprPtr expr; 
+	register xmlXPathCompExprPtr expr;
+	register int t;
+
 	tmp = comp->steps[i].value;
 	comp->steps[i].value = comp->steps[j].value;
 	comp->steps[j].value = tmp;
 	tmp = comp->steps[i].value2;
 	comp->steps[i].value2 = comp->steps[j].value2;
 	comp->steps[j].value2 = tmp;
+	tmp = comp->steps[i].value3;
+	comp->steps[i].value3 = comp->steps[j].value3;
+	comp->steps[j].value3 = tmp;
 	op = comp->steps[i].op;
 	comp->steps[i].op = comp->steps[j].op;
 	comp->steps[j].op = op;
 	expr = comp->steps[i].comp;
 	comp->steps[i].comp = comp->steps[j].comp;
 	comp->steps[j].comp = expr;
+	t = comp->steps[i].previousExtra;
+	comp->steps[i].previousExtra = comp->steps[j].previousExtra;
+	comp->steps[j].previousExtra = t;
+	t = comp->steps[i].indexExtra;
+	comp->steps[i].indexExtra = comp->steps[j].indexExtra;
+	comp->steps[j].indexExtra = t;
+	t = comp->steps[i].lenExtra;
+	comp->steps[i].lenExtra = comp->steps[j].lenExtra;
+	comp->steps[j].lenExtra = t;
 	j--;
 	i++;
     }
-    comp->steps[comp->nbStep++].op = XSLT_OP_END;
+    xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0);
+
     /*
      * detect consecutive XSLT_OP_PREDICATE indicating a direct
      * matching should be done.
@@ -420,7 +471,8 @@ xsltReverseCompMatch(xsltCompMatchPtr co
  ************************************************************************/
 
 static int
-xsltPatPushState(xsltStepStates *states, int step, xmlNodePtr node) {
+xsltPatPushState(xsltTransformContextPtr ctxt, xsltStepStates *states,
+                 int step, xmlNodePtr node) {
     if ((states->states == NULL) || (states->maxstates <= 0)) {
         states->maxstates = 4;
 	states->nbstates = 0;
@@ -431,8 +483,12 @@ xsltPatPushState(xsltStepStates *states,
 
 	tmp = (xsltStepStatePtr) xmlRealloc(states->states,
 			       2 * states->maxstates * sizeof(xsltStepState));
-	if (tmp == NULL)
+	if (tmp == NULL) {
+	    xsltGenericError(xsltGenericErrorContext,
+	     "xsltPatPushState: memory re-allocation failure.\n");
+	    ctxt->state = XSLT_STATE_STOPPED;
 	    return(-1);
+	}
 	states->states = tmp;
 	states->maxstates *= 2;
     }
@@ -738,12 +794,12 @@ restart:
 		    goto rollback;
 		node = node->parent;
 		if ((step->op != XSLT_OP_ELEM) && step->op != XSLT_OP_ALL) {
-		    xsltPatPushState(&states, i, node);
+		    xsltPatPushState(ctxt, &states, i, node);
 		    continue;
 		}
 		i++;
 		if (step->value == NULL) {
-		    xsltPatPushState(&states, i - 1, node);
+		    xsltPatPushState(ctxt, &states, i - 1, node);
 		    continue;
 		}
 		while (node != NULL) {
@@ -764,7 +820,7 @@ restart:
 		}
 		if (node == NULL)
 		    goto rollback;
-		xsltPatPushState(&states, i - 1, node);
+		xsltPatPushState(ctxt, &states, i - 1, node);
 		continue;
             case XSLT_OP_ID: {
 		/* TODO Handle IDs decently, must be done differently */
@@ -1971,7 +2027,7 @@ xsltCompilePatternInternal(const xmlChar
 	/*
 	 * Reverse for faster interpretation.
 	 */
-	xsltReverseCompMatch(element);
+	xsltReverseCompMatch(ctxt, element);
 
 	/*
 	 * Set-up the priority

Reply via email to