Commit message: None
CVE: CVE-2012-2870
CWE: CWE-399
Vulnerability description: libxslt 1.1.26 and earlier, as used in Google Chrome before 21.0.1180.89, does not properly manage memory, which might allow remote attackers to cause a denial of service (application crash) via a crafted XSLT expression that is not properly identified during XPath navigation, related to (1) the xsltCompileLocationPathPattern function in libxslt/pattern.c and (2) the xsltGenerateIdFunction function in libxslt/functions.c.

Project: Chrome
File: pattern.c

xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc,
	           xmlNodePtr node, xsltStylesheetPtr style,
		   xsltTransformContextPtr runtime) {
    return (xsltCompilePatternInternal(pattern, doc, node, style, runtime, 0));
}

Project: Chrome
File: pattern.c

xsltScanLiteral(xsltParserContextPtr ctxt) {
    const xmlChar *q, *cur;
    xmlChar *ret = NULL;
    int val, len;

    SKIP_BLANKS;
    if (CUR == '"') {
        NEXT;
	cur = q = CUR_PTR;
	val = xmlStringCurrentChar(NULL, cur, &len);
	while ((IS_CHAR(val)) && (val != '"')) {
	    cur += len;
	    val = xmlStringCurrentChar(NULL, cur, &len);
	}
	if (!IS_CHAR(val)) {
	    ctxt->error = 1;
	    return(NULL);
	} else {
	    ret = xmlStrndup(q, cur - q);
        }
	cur += len;
	CUR_PTR = cur;
    } else if (CUR == '\'') {
        NEXT;
	cur = q = CUR_PTR;
	val = xmlStringCurrentChar(NULL, cur, &len);
	while ((IS_CHAR(val)) && (val != '\'')) {
	    cur += len;
	    val = xmlStringCurrentChar(NULL, cur, &len);
	}
	if (!IS_CHAR(val)) {
	    ctxt->error = 1;
	    return(NULL);
	} else {
	    ret = xmlStrndup(q, cur - q);
        }
	cur += len;
	CUR_PTR = cur;
    } else {
	/* XP_ERROR(XPATH_START_LITERAL_ERROR); */
	ctxt->error = 1;
	return(NULL);
    }
    return(ret);
}

Project: Chrome

xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
	                xmlNodePtr node, xmlNsPtr *nsList, int nsNr) {
    xsltStepOpPtr sel = NULL;
    xmlDocPtr prevdoc;
    xmlDocPtr doc;
    xmlXPathObjectPtr list;
    int ix, j;
    int nocache = 0;
    int isRVT;

    doc = node->doc;
    if (XSLT_IS_RES_TREE_FRAG(doc))
	isRVT = 1;
    else
	isRVT = 0;
    sel = &comp->steps[0]; /* store extra in first step arbitrarily */

    prevdoc = (xmlDocPtr)
	XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
    ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
    list = (xmlXPathObjectPtr)
	XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
    
    if ((list == NULL) || (prevdoc != doc)) {
	xmlXPathObjectPtr newlist;
	xmlNodePtr parent = node->parent;
	xmlDocPtr olddoc;
	xmlNodePtr oldnode;
	int oldNsNr;
	xmlNsPtr *oldNamespaces;

	oldnode = ctxt->xpathCtxt->node;
	olddoc = ctxt->xpathCtxt->doc;
	oldNsNr = ctxt->xpathCtxt->nsNr;
	oldNamespaces = ctxt->xpathCtxt->namespaces;
	ctxt->xpathCtxt->node = node;
	ctxt->xpathCtxt->doc = doc;
	ctxt->xpathCtxt->namespaces = nsList;
	ctxt->xpathCtxt->nsNr = nsNr;
	newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt);
	ctxt->xpathCtxt->node = oldnode;
	ctxt->xpathCtxt->doc = olddoc;
	ctxt->xpathCtxt->namespaces = oldNamespaces;
	ctxt->xpathCtxt->nsNr = oldNsNr;
	if (newlist == NULL)
	    return(-1);
	if (newlist->type != XPATH_NODESET) {
	    xmlXPathFreeObject(newlist);
	    return(-1);
	}
	ix = 0;

	if ((parent == NULL) || (node->doc == NULL) || isRVT)
	    nocache = 1;
	
	if (nocache == 0) {
	    if (list != NULL)
		xmlXPathFreeObject(list);
	    list = newlist;

	    XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) =
		(void *) list;
	    XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
		(void *) doc;
	    XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
		0;
	    XSLT_RUNTIME_EXTRA_FREE(ctxt, sel->lenExtra) =
		(xmlFreeFunc) xmlXPathFreeObject;
	} else
	    list = newlist;
    }
    if ((list->nodesetval == NULL) ||
	(list->nodesetval->nodeNr <= 0)) {
	if (nocache == 1)
	    xmlXPathFreeObject(list);
	return(0);
    }
    /* TODO: store the index and use it for the scan */
    if (ix == 0) {
	for (j = 0;j < list->nodesetval->nodeNr;j++) {
	    if (list->nodesetval->nodeTab[j] == node) {
		if (nocache == 1)
		    xmlXPathFreeObject(list);
		return(1);
	    }
	}
    } else {
    }
    if (nocache == 1)
	xmlXPathFreeObject(list);
    return(0);
}

Project: Chrome
File: pattern.c

xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node,
	              xsltCompMatchPtr comp) {
    int ret;

    if ((ctxt == NULL) || (node == NULL))
	return(-1);
    while (comp != NULL) {
	ret = xsltTestCompMatch(ctxt, comp, node, NULL, NULL);
	if (ret == 1)
	    return(1);
	comp = comp->next;
    }
    return(0);
}