1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-08-08 21:42:07 +03:00

malloc-fail: Fix null deref in exsltFuncFunctionFunction

Found with libFuzzer, see #84.
This commit is contained in:
Nick Wellnhofer
2023-02-26 16:53:18 +01:00
parent 6c1e520618
commit 7364666ba3

View File

@@ -286,16 +286,12 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
exsltFuncData *data; exsltFuncData *data;
exsltFuncFunctionData *func; exsltFuncFunctionData *func;
xmlNodePtr paramNode, oldInsert, oldXPNode, fake; xmlNodePtr paramNode, oldInsert, oldXPNode, fake;
int oldBase; int oldBase, newBase;
void *oldCtxtVar; void *oldCtxtVar;
xsltStackElemPtr params = NULL, param; xsltStackElemPtr params = NULL, param;
xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt); xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
int i, notSet; int i;
struct objChain { xmlXPathObjectPtr *args = NULL;
struct objChain *next;
xmlXPathObjectPtr obj;
};
struct objChain *savedObjChain = NULL, *savedObj;
/* /*
* retrieve func:function template * retrieve func:function template
@@ -357,6 +353,10 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
/* Evaluating templates can change the XPath context node. */ /* Evaluating templates can change the XPath context node. */
oldXPNode = tctxt->xpathCtxt->node; oldXPNode = tctxt->xpathCtxt->node;
fake = xmlNewDocNode(tctxt->output, NULL,
(const xmlChar *)"fake", NULL);
if (fake == NULL)
goto error;
/* /*
* We have a problem with the evaluation of function parameters. * We have a problem with the evaluation of function parameters.
* The original library code did not evaluate XPath expressions until * The original library code did not evaluate XPath expressions until
@@ -379,16 +379,15 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
* In order to give the function params and variables a new 'scope' * In order to give the function params and variables a new 'scope'
* we change varsBase in the context. * we change varsBase in the context.
*/ */
oldBase = tctxt->varsBase; newBase = tctxt->varsNr;
tctxt->varsBase = tctxt->varsNr;
/* If there are any parameters */ /* If there are any parameters */
if (paramNode != NULL) { if (paramNode != NULL) {
args = (xmlXPathObjectPtr *) xmlMalloc(sizeof(*args) * nargs);
if (args == NULL)
goto error;
/* Fetch the stored argument values from the caller */ /* Fetch the stored argument values from the caller */
for (i = 0; i < nargs; i++) { for (i = nargs - 1; i >= 0; i--) {
savedObj = xmlMalloc(sizeof(struct objChain)); args[i] = valuePop(ctxt);
savedObj->next = savedObjChain;
savedObj->obj = valuePop(ctxt);
savedObjChain = savedObj;
} }
/* /*
@@ -405,17 +404,20 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
* as arguments from the caller * as arguments from the caller
* Calculate the number of un-set parameters * Calculate the number of un-set parameters
*/ */
notSet = func->nargs - nargs; for (i = 0; i < func->nargs; i++) {
for (; i > 0; i--) {
param = xsltParseStylesheetCallerParam (tctxt, paramNode); param = xsltParseStylesheetCallerParam (tctxt, paramNode);
if (i > notSet) { /* if parameter value set */ if (param == NULL) {
xsltLocalVariablePop(tctxt, newBase, -2);
xsltFreeStackElemList(params);
for (; i < nargs; i++)
xmlXPathFreeObject(args[i]);
goto error;
}
if (i < nargs) { /* if parameter value set */
param->computed = 1; param->computed = 1;
if (param->value != NULL) if (param->value != NULL)
xmlXPathFreeObject(param->value); xmlXPathFreeObject(param->value);
savedObj = savedObjChain; /* get next val from chain */ param->value = args[i];
param->value = savedObj->obj;
savedObjChain = savedObjChain->next;
xmlFree(savedObj);
} }
xsltLocalVariablePush(tctxt, param, -1); xsltLocalVariablePush(tctxt, param, -1);
param->next = params; param->next = params;
@@ -427,11 +429,11 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
* Actual processing. The context variable is cleared and restored * Actual processing. The context variable is cleared and restored
* when func:result is evaluated. * when func:result is evaluated.
*/ */
fake = xmlNewDocNode(tctxt->output, NULL, oldBase = tctxt->varsBase;
(const xmlChar *)"fake", NULL);
oldInsert = tctxt->insert; oldInsert = tctxt->insert;
oldCtxtVar = data->ctxtVar; oldCtxtVar = data->ctxtVar;
data->ctxtVar = tctxt->contextVariable; data->ctxtVar = tctxt->contextVariable;
tctxt->varsBase = newBase;
tctxt->insert = fake; tctxt->insert = fake;
tctxt->contextVariable = NULL; tctxt->contextVariable = NULL;
xsltApplyOneTemplate (tctxt, tctxt->node, xsltApplyOneTemplate (tctxt, tctxt->node,
@@ -470,14 +472,14 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
"{%s}%s: cannot write to result tree while " "{%s}%s: cannot write to result tree while "
"executing a function\n", "executing a function\n",
ctxt->context->functionURI, ctxt->context->function); ctxt->context->functionURI, ctxt->context->function);
xmlFreeNode(fake);
xmlXPathFreeObject(ret); xmlXPathFreeObject(ret);
goto error; goto error;
} }
xmlFreeNode(fake);
valuePush(ctxt, ret); valuePush(ctxt, ret);
error: error:
xmlFree(args);
xmlFreeNode(fake);
tctxt->depth--; tctxt->depth--;
} }