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

regexp: Check reallocations for overflow

This commit is contained in:
Nick Wellnhofer
2024-12-15 23:23:10 +01:00
parent ae41cf9af5
commit 0d6136da21

View File

@@ -30,6 +30,7 @@
#include <libxml/xmlunicode.h> #include <libxml/xmlunicode.h>
#include "private/error.h" #include "private/error.h"
#include "private/memory.h"
#include "private/regexp.h" #include "private/regexp.h"
#ifndef SIZE_MAX #ifndef SIZE_MAX
@@ -1174,26 +1175,23 @@ xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom,
ERROR("add range: atom is not ranges"); ERROR("add range: atom is not ranges");
return(NULL); return(NULL);
} }
if (atom->maxRanges == 0) { if (atom->nbRanges >= atom->maxRanges) {
atom->maxRanges = 4;
atom->ranges = (xmlRegRangePtr *) xmlMalloc(atom->maxRanges *
sizeof(xmlRegRangePtr));
if (atom->ranges == NULL) {
xmlRegexpErrMemory(ctxt);
atom->maxRanges = 0;
return(NULL);
}
} else if (atom->nbRanges >= atom->maxRanges) {
xmlRegRangePtr *tmp; xmlRegRangePtr *tmp;
atom->maxRanges *= 2; int newSize;
tmp = (xmlRegRangePtr *) xmlRealloc(atom->ranges, atom->maxRanges *
sizeof(xmlRegRangePtr)); newSize = xmlGrowCapacity(atom->maxRanges, sizeof(tmp[0]),
4, XML_MAX_ITEMS);
if (newSize < 0) {
xmlRegexpErrMemory(ctxt);
return(NULL);
}
tmp = xmlRealloc(atom->ranges, newSize * sizeof(tmp[0]));
if (tmp == NULL) { if (tmp == NULL) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
atom->maxRanges /= 2;
return(NULL); return(NULL);
} }
atom->ranges = tmp; atom->ranges = tmp;
atom->maxRanges = newSize;
} }
range = xmlRegNewRange(ctxt, neg, type, start, end); range = xmlRegNewRange(ctxt, neg, type, start, end);
if (range == NULL) if (range == NULL)
@@ -1206,26 +1204,23 @@ xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom,
static int static int
xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) { xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) {
if (ctxt->maxCounters == 0) { if (ctxt->nbCounters >= ctxt->maxCounters) {
ctxt->maxCounters = 4; xmlRegCounter *tmp;
ctxt->counters = (xmlRegCounter *) xmlMalloc(ctxt->maxCounters * int newSize;
sizeof(xmlRegCounter));
if (ctxt->counters == NULL) { newSize = xmlGrowCapacity(ctxt->maxCounters, sizeof(tmp[0]),
4, XML_MAX_ITEMS);
if (newSize < 0) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
ctxt->maxCounters = 0;
return(-1); return(-1);
} }
} else if (ctxt->nbCounters >= ctxt->maxCounters) { tmp = xmlRealloc(ctxt->counters, newSize * sizeof(tmp[0]));
xmlRegCounter *tmp;
ctxt->maxCounters *= 2;
tmp = (xmlRegCounter *) xmlRealloc(ctxt->counters, ctxt->maxCounters *
sizeof(xmlRegCounter));
if (tmp == NULL) { if (tmp == NULL) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
ctxt->maxCounters /= 2;
return(-1); return(-1);
} }
ctxt->counters = tmp; ctxt->counters = tmp;
ctxt->maxCounters = newSize;
} }
ctxt->counters[ctxt->nbCounters].min = -1; ctxt->counters[ctxt->nbCounters].min = -1;
ctxt->counters[ctxt->nbCounters].max = -1; ctxt->counters[ctxt->nbCounters].max = -1;
@@ -1239,10 +1234,16 @@ xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
return(-1); return(-1);
} }
if (ctxt->nbAtoms >= ctxt->maxAtoms) { if (ctxt->nbAtoms >= ctxt->maxAtoms) {
size_t newSize = ctxt->maxAtoms ? ctxt->maxAtoms * 2 : 4;
xmlRegAtomPtr *tmp; xmlRegAtomPtr *tmp;
int newSize;
tmp = xmlRealloc(ctxt->atoms, newSize * sizeof(xmlRegAtomPtr)); newSize = xmlGrowCapacity(ctxt->maxAtoms, sizeof(tmp[0]),
4, XML_MAX_ITEMS);
if (newSize < 0) {
xmlRegexpErrMemory(ctxt);
return(-1);
}
tmp = xmlRealloc(ctxt->atoms, newSize * sizeof(tmp[0]));
if (tmp == NULL) { if (tmp == NULL) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
return(-1); return(-1);
@@ -1258,26 +1259,23 @@ xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
static void static void
xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target, xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target,
int from) { int from) {
if (target->maxTransTo == 0) { if (target->nbTransTo >= target->maxTransTo) {
target->maxTransTo = 8; int *tmp;
target->transTo = (int *) xmlMalloc(target->maxTransTo * int newSize;
sizeof(int));
if (target->transTo == NULL) { newSize = xmlGrowCapacity(target->maxTransTo, sizeof(tmp[0]),
8, XML_MAX_ITEMS);
if (newSize < 0) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
target->maxTransTo = 0;
return; return;
} }
} else if (target->nbTransTo >= target->maxTransTo) { tmp = xmlRealloc(target->transTo, newSize * sizeof(tmp[0]));
int *tmp;
target->maxTransTo *= 2;
tmp = (int *) xmlRealloc(target->transTo, target->maxTransTo *
sizeof(int));
if (tmp == NULL) { if (tmp == NULL) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
target->maxTransTo /= 2;
return; return;
} }
target->transTo = tmp; target->transTo = tmp;
target->maxTransTo = newSize;
} }
target->transTo[target->nbTransTo] = from; target->transTo[target->nbTransTo] = from;
target->nbTransTo++; target->nbTransTo++;
@@ -1314,26 +1312,23 @@ xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
} }
} }
if (state->maxTrans == 0) { if (state->nbTrans >= state->maxTrans) {
state->maxTrans = 8; xmlRegTrans *tmp;
state->trans = (xmlRegTrans *) xmlMalloc(state->maxTrans * int newSize;
sizeof(xmlRegTrans));
if (state->trans == NULL) { newSize = xmlGrowCapacity(state->maxTrans, sizeof(tmp[0]),
8, XML_MAX_ITEMS);
if (newSize < 0) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
state->maxTrans = 0;
return; return;
} }
} else if (state->nbTrans >= state->maxTrans) { tmp = xmlRealloc(state->trans, newSize * sizeof(tmp[0]));
xmlRegTrans *tmp;
state->maxTrans *= 2;
tmp = (xmlRegTrans *) xmlRealloc(state->trans, state->maxTrans *
sizeof(xmlRegTrans));
if (tmp == NULL) { if (tmp == NULL) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
state->maxTrans /= 2;
return; return;
} }
state->trans = tmp; state->trans = tmp;
state->maxTrans = newSize;
} }
state->trans[state->nbTrans].atom = atom; state->trans[state->nbTrans].atom = atom;
@@ -1350,9 +1345,15 @@ xmlRegStatePush(xmlRegParserCtxtPtr ctxt) {
xmlRegStatePtr state; xmlRegStatePtr state;
if (ctxt->nbStates >= ctxt->maxStates) { if (ctxt->nbStates >= ctxt->maxStates) {
size_t newSize = ctxt->maxStates ? ctxt->maxStates * 2 : 4;
xmlRegStatePtr *tmp; xmlRegStatePtr *tmp;
int newSize;
newSize = xmlGrowCapacity(ctxt->maxStates, sizeof(tmp[0]),
4, XML_MAX_ITEMS);
if (newSize < 0) {
xmlRegexpErrMemory(ctxt);
return(NULL);
}
tmp = xmlRealloc(ctxt->states, newSize * sizeof(tmp[0])); tmp = xmlRealloc(ctxt->states, newSize * sizeof(tmp[0]));
if (tmp == NULL) { if (tmp == NULL) {
xmlRegexpErrMemory(ctxt); xmlRegexpErrMemory(ctxt);
@@ -3034,30 +3035,24 @@ xmlFARegExecSave(xmlRegExecCtxtPtr exec) {
exec->nbPush++; exec->nbPush++;
#endif #endif
if (exec->maxRollbacks == 0) { if (exec->nbRollbacks >= exec->maxRollbacks) {
exec->maxRollbacks = 4; xmlRegExecRollback *tmp;
exec->rollbacks = (xmlRegExecRollback *) xmlMalloc(exec->maxRollbacks * int newSize;
sizeof(xmlRegExecRollback)); int len = exec->nbRollbacks;
if (exec->rollbacks == NULL) {
exec->maxRollbacks = 0; newSize = xmlGrowCapacity(exec->maxRollbacks, sizeof(tmp[0]),
4, XML_MAX_ITEMS);
if (newSize < 0) {
exec->status = XML_REGEXP_OUT_OF_MEMORY; exec->status = XML_REGEXP_OUT_OF_MEMORY;
return; return;
} }
memset(exec->rollbacks, 0, tmp = xmlRealloc(exec->rollbacks, newSize * sizeof(tmp[0]));
exec->maxRollbacks * sizeof(xmlRegExecRollback));
} else if (exec->nbRollbacks >= exec->maxRollbacks) {
xmlRegExecRollback *tmp;
int len = exec->maxRollbacks;
exec->maxRollbacks *= 2;
tmp = (xmlRegExecRollback *) xmlRealloc(exec->rollbacks,
exec->maxRollbacks * sizeof(xmlRegExecRollback));
if (tmp == NULL) { if (tmp == NULL) {
exec->maxRollbacks /= 2;
exec->status = XML_REGEXP_OUT_OF_MEMORY; exec->status = XML_REGEXP_OUT_OF_MEMORY;
return; return;
} }
exec->rollbacks = tmp; exec->rollbacks = tmp;
exec->maxRollbacks = newSize;
tmp = &exec->rollbacks[len]; tmp = &exec->rollbacks[len];
memset(tmp, 0, (exec->maxRollbacks - len) * sizeof(xmlRegExecRollback)); memset(tmp, 0, (exec->maxRollbacks - len) * sizeof(xmlRegExecRollback));
} }
@@ -3512,27 +3507,27 @@ xmlRegExecSetErrString(xmlRegExecCtxtPtr exec, const xmlChar *value) {
static void static void
xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value, xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value,
void *data) { void *data) {
if (exec->inputStackMax == 0) { if (exec->inputStackNr + 1 >= exec->inputStackMax) {
exec->inputStackMax = 4; xmlRegInputTokenPtr tmp;
exec->inputStack = (xmlRegInputTokenPtr) int newSize;
xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken));
if (exec->inputStack == NULL) { newSize = xmlGrowCapacity(exec->inputStackMax, sizeof(tmp[0]),
exec->inputStackMax = 0; 4, XML_MAX_ITEMS);
if (newSize < 0) {
exec->status = XML_REGEXP_OUT_OF_MEMORY; exec->status = XML_REGEXP_OUT_OF_MEMORY;
return; return;
} }
} else if (exec->inputStackNr + 1 >= exec->inputStackMax) { #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
xmlRegInputTokenPtr tmp; if (newSize < 2)
newSize = 2;
exec->inputStackMax *= 2; #endif
tmp = (xmlRegInputTokenPtr) xmlRealloc(exec->inputStack, tmp = xmlRealloc(exec->inputStack, newSize * sizeof(tmp[0]));
exec->inputStackMax * sizeof(xmlRegInputToken));
if (tmp == NULL) { if (tmp == NULL) {
exec->inputStackMax /= 2;
exec->status = XML_REGEXP_OUT_OF_MEMORY; exec->status = XML_REGEXP_OUT_OF_MEMORY;
return; return;
} }
exec->inputStack = tmp; exec->inputStack = tmp;
exec->inputStackMax = newSize;
} }
if (value == NULL) { if (value == NULL) {
exec->inputStack[exec->inputStackNr].value = NULL; exec->inputStack[exec->inputStackNr].value = NULL;
@@ -7514,14 +7509,21 @@ xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0); len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0);
while (len < 0) { while (len < 0) {
const xmlChar **temp; const xmlChar **temp;
temp = (const xmlChar **) xmlRealloc((xmlChar **) tab, ctxt->tabSize * 2 * int newSize;
sizeof(const xmlChar *));
newSize = xmlGrowCapacity(ctxt->tabSize, sizeof(temp[0]),
40, XML_MAX_ITEMS);
if (newSize < 0) {
xmlFree(tab);
return(NULL);
}
temp = xmlRealloc(tab, newSize * sizeof(temp[0]));
if (temp == NULL) { if (temp == NULL) {
xmlFree((xmlChar **) tab); xmlFree(tab);
return(NULL); return(NULL);
} }
tab = temp; tab = temp;
ctxt->tabSize *= 2; ctxt->tabSize = newSize;
len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0); len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0);
} }
for (i = 0;i < len;i++) { for (i = 0;i < len;i++) {