1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-21 14:53:44 +03:00

malloc-fail: Fix memory leak after xmlRegNewState

Invoke xmlRegNewState from xmlRegStatePush to simplify error handling.

Found with libFuzzer, see #344.
This commit is contained in:
Nick Wellnhofer
2023-02-15 01:00:03 +01:00
parent cb4334b7ab
commit e60c9f4c4b

View File

@@ -1439,33 +1439,31 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
xmlRegStateAddTransTo(ctxt, target, state->no); xmlRegStateAddTransTo(ctxt, target, state->no);
} }
static int static xmlRegStatePtr
xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) { xmlRegStatePush(xmlRegParserCtxtPtr ctxt) {
if (state == NULL) return(-1); xmlRegStatePtr state;
if (ctxt->maxStates == 0) {
ctxt->maxStates = 4; if (ctxt->nbStates >= ctxt->maxStates) {
ctxt->states = (xmlRegStatePtr *) xmlMalloc(ctxt->maxStates * size_t newSize = ctxt->maxStates ? ctxt->maxStates * 2 : 4;
sizeof(xmlRegStatePtr));
if (ctxt->states == NULL) {
xmlRegexpErrMemory(ctxt, "adding state");
ctxt->maxStates = 0;
return(-1);
}
} else if (ctxt->nbStates >= ctxt->maxStates) {
xmlRegStatePtr *tmp; xmlRegStatePtr *tmp;
ctxt->maxStates *= 2;
tmp = (xmlRegStatePtr *) xmlRealloc(ctxt->states, ctxt->maxStates * tmp = xmlRealloc(ctxt->states, newSize * sizeof(tmp[0]));
sizeof(xmlRegStatePtr));
if (tmp == NULL) { if (tmp == NULL) {
xmlRegexpErrMemory(ctxt, "adding state"); xmlRegexpErrMemory(ctxt, "adding state");
ctxt->maxStates /= 2; return(NULL);
return(-1);
} }
ctxt->states = tmp; ctxt->states = tmp;
ctxt->maxStates = newSize;
} }
state = xmlRegNewState(ctxt);
if (state == NULL)
return(NULL);
state->no = ctxt->nbStates; state->no = ctxt->nbStates;
ctxt->states[ctxt->nbStates++] = state; ctxt->states[ctxt->nbStates++] = state;
return(0);
return(state);
} }
/** /**
@@ -1476,19 +1474,21 @@ xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
* @lax: * @lax:
* *
*/ */
static void static int
xmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt, xmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt,
xmlRegStatePtr from, xmlRegStatePtr to, xmlRegStatePtr from, xmlRegStatePtr to,
int lax) { int lax) {
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(ctxt); to = xmlRegStatePush(ctxt);
xmlRegStatePush(ctxt, to); if (to == NULL)
return(-1);
ctxt->state = to; ctxt->state = to;
} }
if (lax) if (lax)
xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_LAX_COUNTER); xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_LAX_COUNTER);
else else
xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_COUNTER); xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_COUNTER);
return(0);
} }
/** /**
@@ -1498,15 +1498,17 @@ xmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt,
* @to: the target state or NULL for building a new one * @to: the target state or NULL for building a new one
* *
*/ */
static void static int
xmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt, xmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt,
xmlRegStatePtr from, xmlRegStatePtr to) { xmlRegStatePtr from, xmlRegStatePtr to) {
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(ctxt); to = xmlRegStatePush(ctxt);
xmlRegStatePush(ctxt, to); if (to == NULL)
return(-1);
ctxt->state = to; ctxt->state = to;
} }
xmlRegStateAddTrans(ctxt, from, NULL, to, -1, -1); xmlRegStateAddTrans(ctxt, from, NULL, to, -1, -1);
return(0);
} }
/** /**
@@ -1517,15 +1519,17 @@ xmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt,
* counter: the counter for that transition * counter: the counter for that transition
* *
*/ */
static void static int
xmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt, xmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt,
xmlRegStatePtr from, xmlRegStatePtr to, int counter) { xmlRegStatePtr from, xmlRegStatePtr to, int counter) {
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(ctxt); to = xmlRegStatePush(ctxt);
xmlRegStatePush(ctxt, to); if (to == NULL)
return(-1);
ctxt->state = to; ctxt->state = to;
} }
xmlRegStateAddTrans(ctxt, from, NULL, to, counter, -1); xmlRegStateAddTrans(ctxt, from, NULL, to, counter, -1);
return(0);
} }
/** /**
@@ -1536,15 +1540,17 @@ xmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt,
* counter: the counter for that transition * counter: the counter for that transition
* *
*/ */
static void static int
xmlFAGenerateCountedTransition(xmlRegParserCtxtPtr ctxt, xmlFAGenerateCountedTransition(xmlRegParserCtxtPtr ctxt,
xmlRegStatePtr from, xmlRegStatePtr to, int counter) { xmlRegStatePtr from, xmlRegStatePtr to, int counter) {
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(ctxt); to = xmlRegStatePush(ctxt);
xmlRegStatePush(ctxt, to); if (to == NULL)
return(-1);
ctxt->state = to; ctxt->state = to;
} }
xmlRegStateAddTrans(ctxt, from, NULL, to, -1, counter); xmlRegStateAddTrans(ctxt, from, NULL, to, -1, counter);
return(0);
} }
/** /**
@@ -1583,8 +1589,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
#ifdef DV #ifdef DV
} else if ((to == NULL) && (atom->quant != XML_REGEXP_QUANT_RANGE) && } else if ((to == NULL) && (atom->quant != XML_REGEXP_QUANT_RANGE) &&
(atom->quant != XML_REGEXP_QUANT_ONCE)) { (atom->quant != XML_REGEXP_QUANT_ONCE)) {
to = xmlRegNewState(ctxt); to = xmlRegStatePush(ctxt, to);
xmlRegStatePush(ctxt, to); if (to == NULL)
return(-1);
ctxt->state = to; ctxt->state = to;
xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to); xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to);
#endif #endif
@@ -1624,8 +1631,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
if (to != NULL) { if (to != NULL) {
newstate = to; newstate = to;
} else { } else {
newstate = xmlRegNewState(ctxt); newstate = xmlRegStatePush(ctxt);
xmlRegStatePush(ctxt, newstate); if (newstate == NULL)
return(-1);
} }
/* /*
@@ -1705,12 +1713,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
* we can discard the atom and generate an epsilon transition instead * we can discard the atom and generate an epsilon transition instead
*/ */
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(ctxt); to = xmlRegStatePush(ctxt);
if (to != NULL) if (to == NULL)
xmlRegStatePush(ctxt, to);
else {
return(-1); return(-1);
}
} }
xmlFAGenerateEpsilonTransition(ctxt, from, to); xmlFAGenerateEpsilonTransition(ctxt, from, to);
ctxt->state = to; ctxt->state = to;
@@ -1718,12 +1723,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
return(0); return(0);
} }
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(ctxt); to = xmlRegStatePush(ctxt);
if (to != NULL) if (to == NULL)
xmlRegStatePush(ctxt, to);
else {
return(-1); return(-1);
}
} }
end = to; end = to;
if ((atom->quant == XML_REGEXP_QUANT_MULT) || if ((atom->quant == XML_REGEXP_QUANT_MULT) ||
@@ -1735,12 +1737,9 @@ xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
*/ */
xmlRegStatePtr tmp; xmlRegStatePtr tmp;
tmp = xmlRegNewState(ctxt); tmp = xmlRegStatePush(ctxt);
if (tmp != NULL) if (tmp == NULL)
xmlRegStatePush(ctxt, tmp);
else {
return(-1); return(-1);
}
xmlFAGenerateEpsilonTransition(ctxt, tmp, to); xmlFAGenerateEpsilonTransition(ctxt, tmp, to);
to = tmp; to = tmp;
} }
@@ -5612,9 +5611,11 @@ xmlRegexpCompile(const xmlChar *regexp) {
return(NULL); return(NULL);
/* initialize the parser */ /* initialize the parser */
ctxt->state = xmlRegStatePush(ctxt);
if (ctxt->state == NULL)
return(NULL);
ctxt->start = ctxt->state;
ctxt->end = NULL; ctxt->end = NULL;
ctxt->start = ctxt->state = xmlRegNewState(ctxt);
xmlRegStatePush(ctxt, ctxt->start);
/* parse the expression building an automata */ /* parse the expression building an automata */
xmlFAParseRegExp(ctxt, 1); xmlFAParseRegExp(ctxt, 1);
@@ -5762,18 +5763,15 @@ xmlNewAutomata(void) {
return(NULL); return(NULL);
/* initialize the parser */ /* initialize the parser */
ctxt->state = xmlRegStatePush(ctxt);
if (ctxt->state == NULL) {
xmlFreeAutomata(ctxt);
return(NULL);
}
ctxt->start = ctxt->state;
ctxt->end = NULL; ctxt->end = NULL;
ctxt->start = ctxt->state = xmlRegNewState(ctxt);
if (ctxt->start == NULL) {
xmlFreeAutomata(ctxt);
return(NULL);
}
ctxt->start->type = XML_REGEXP_START_STATE; ctxt->start->type = XML_REGEXP_START_STATE;
if (xmlRegStatePush(ctxt, ctxt->start) < 0) {
xmlRegFreeState(ctxt->start);
xmlFreeAutomata(ctxt);
return(NULL);
}
ctxt->flags = 0; ctxt->flags = 0;
return(ctxt); return(ctxt);
@@ -6071,8 +6069,9 @@ xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
/* xmlFAGenerateTransitions(am, from, to, atom); */ /* xmlFAGenerateTransitions(am, from, to, atom); */
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(am); to = xmlRegStatePush(am);
xmlRegStatePush(am, to); if (to == NULL)
return(NULL);
} }
xmlRegStateAddTrans(am, from, atom, to, counter, -1); xmlRegStateAddTrans(am, from, atom, to, counter, -1);
xmlRegAtomPush(am, atom); xmlRegAtomPush(am, atom);
@@ -6137,8 +6136,9 @@ xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
/* xmlFAGenerateTransitions(am, from, to, atom); */ /* xmlFAGenerateTransitions(am, from, to, atom); */
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(am); to = xmlRegStatePush(am);
xmlRegStatePush(am, to); if (to == NULL)
return(NULL);
} }
xmlRegStateAddTrans(am, from, atom, to, counter, -1); xmlRegStateAddTrans(am, from, atom, to, counter, -1);
xmlRegAtomPush(am, atom); xmlRegAtomPush(am, atom);
@@ -6223,8 +6223,9 @@ xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
/* xmlFAGenerateTransitions(am, from, to, atom); */ /* xmlFAGenerateTransitions(am, from, to, atom); */
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(am); to = xmlRegStatePush(am);
xmlRegStatePush(am, to); if (to == NULL)
return(NULL);
} }
xmlRegStateAddTrans(am, from, atom, to, counter, -1); xmlRegStateAddTrans(am, from, atom, to, counter, -1);
xmlRegAtomPush(am, atom); xmlRegAtomPush(am, atom);
@@ -6282,8 +6283,9 @@ xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
/* xmlFAGenerateTransitions(am, from, to, atom); */ /* xmlFAGenerateTransitions(am, from, to, atom); */
if (to == NULL) { if (to == NULL) {
to = xmlRegNewState(am); to = xmlRegStatePush(am);
xmlRegStatePush(am, to); if (to == NULL)
return(NULL);
} }
xmlRegStateAddTrans(am, from, atom, to, counter, -1); xmlRegStateAddTrans(am, from, atom, to, counter, -1);
xmlRegAtomPush(am, atom); xmlRegAtomPush(am, atom);
@@ -6301,13 +6303,9 @@ xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
*/ */
xmlAutomataStatePtr xmlAutomataStatePtr
xmlAutomataNewState(xmlAutomataPtr am) { xmlAutomataNewState(xmlAutomataPtr am) {
xmlAutomataStatePtr to;
if (am == NULL) if (am == NULL)
return(NULL); return(NULL);
to = xmlRegNewState(am); return(xmlRegStatePush(am));
xmlRegStatePush(am, to);
return(to);
} }
/** /**