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:
148
xmlregexp.c
148
xmlregexp.c
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user