1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-31 06:50:06 +03:00

parser: Check reallocations for overflow

This commit is contained in:
Nick Wellnhofer 2024-12-15 23:36:04 +01:00
parent 5320a4aa38
commit 8231c03663
2 changed files with 289 additions and 211 deletions

467
parser.c
View File

@ -73,6 +73,7 @@
#include "private/error.h"
#include "private/html.h"
#include "private/io.h"
#include "private/memory.h"
#include "private/parser.h"
#define NS_INDEX_EMPTY INT_MAX
@ -88,6 +89,8 @@
#define SIZE_MAX ((size_t) -1)
#endif
#define XML_MAX_ATTRS 100000000 /* 100 million */
struct _xmlStartTag {
const xmlChar *prefix;
const xmlChar *URI;
@ -1104,7 +1107,19 @@ xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
xmlDefAttrsPtr temp;
int newSize;
newSize = (defaults != NULL) ? 2 * defaults->maxAttrs : 4;
if (defaults == NULL) {
newSize = 4;
} else {
if ((defaults->maxAttrs >= XML_MAX_ATTRS) ||
((size_t) defaults->maxAttrs >
SIZE_MAX / 2 / sizeof(temp[0]) - sizeof(*defaults)))
goto mem_error;
if (defaults->maxAttrs > XML_MAX_ATTRS / 2)
newSize = XML_MAX_ATTRS;
else
newSize = defaults->maxAttrs * 2;
}
temp = xmlRealloc(defaults,
sizeof(*defaults) + newSize * sizeof(xmlDefAttr));
if (temp == NULL)
@ -1670,9 +1685,11 @@ xmlParserNsGrow(xmlParserCtxtPtr ctxt) {
xmlParserNsExtra *extra;
int newSize;
if (ctxt->nsMax > INT_MAX / 2)
newSize = xmlGrowCapacity(ctxt->nsMax,
sizeof(table[0]) + sizeof(extra[0]),
16, XML_MAX_ITEMS);
if (newSize < 0)
goto error;
newSize = ctxt->nsMax ? ctxt->nsMax * 2 : 16;
table = xmlRealloc(ctxt->nsTab, 2 * newSize * sizeof(table[0]));
if (table == NULL)
@ -1895,35 +1912,31 @@ static int
xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt) {
const xmlChar **atts;
unsigned *attallocs;
int maxatts = ctxt->maxatts;
int newSize;
if (maxatts == 0) {
maxatts = 50;
} else {
if ((maxatts > INT_MAX / 2 - 5) ||
((size_t) maxatts > SIZE_MAX / 2 / sizeof(const xmlChar *)))
goto mem_error;
maxatts *= 2;
newSize = xmlGrowCapacity(ctxt->maxatts / 5,
sizeof(atts[0]) * 5 + sizeof(attallocs[0]),
10, XML_MAX_ATTRS);
if (newSize < 0) {
xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT,
"Maximum number of attributes exceeded");
return(-1);
}
atts = xmlMalloc(maxatts * sizeof(const xmlChar *));
atts = xmlRealloc(ctxt->atts, newSize * sizeof(atts[0]) * 5);
if (atts == NULL)
goto mem_error;
attallocs = xmlRealloc(ctxt->attallocs,
(maxatts / 5) * sizeof(attallocs[0]));
if (attallocs == NULL) {
xmlFree(atts);
goto mem_error;
}
if (ctxt->maxatts > 0)
memcpy(atts, ctxt->atts, ctxt->maxatts * sizeof(const xmlChar *));
xmlFree(ctxt->atts);
ctxt->atts = atts;
ctxt->attallocs = attallocs;
ctxt->maxatts = maxatts;
return(maxatts);
attallocs = xmlRealloc(ctxt->attallocs,
newSize * sizeof(attallocs[0]));
if (attallocs == NULL)
goto mem_error;
ctxt->attallocs = attallocs;
ctxt->maxatts = newSize * 5;
return(0);
mem_error:
xmlErrMemory(ctxt);
@ -1949,22 +1962,23 @@ xmlCtxtPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
return(-1);
maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 40 : 20;
if (ctxt->inputNr > maxDepth) {
xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
"Maximum entity nesting depth exceeded");
xmlHaltParser(ctxt);
return(-1);
}
if (ctxt->inputNr >= ctxt->inputMax) {
size_t newSize = ctxt->inputMax * 2;
xmlParserInputPtr *tmp;
int newSize;
tmp = (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
newSize * sizeof(*tmp));
newSize = xmlGrowCapacity(ctxt->inputMax, sizeof(tmp[0]),
5, maxDepth);
if (newSize < 0) {
xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
"Maximum entity nesting depth exceeded");
xmlHaltParser(ctxt);
return(-1);
}
tmp = xmlRealloc(ctxt->inputTab, newSize * sizeof(tmp[0]));
if (tmp == NULL) {
xmlErrMemory(ctxt);
return (-1);
return(-1);
}
ctxt->inputTab = tmp;
ctxt->inputMax = newSize;
@ -2069,32 +2083,34 @@ inputPop(xmlParserCtxtPtr ctxt)
int
nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
{
int maxDepth;
if (ctxt == NULL)
return(0);
maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256;
if (ctxt->nodeNr > maxDepth) {
xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT,
"Excessive depth in document: %d use XML_PARSE_HUGE option\n",
ctxt->nodeNr);
xmlHaltParser(ctxt);
return(-1);
}
if (ctxt->nodeNr >= ctxt->nodeMax) {
int maxDepth = (ctxt->options & XML_PARSE_HUGE) ? 2048 : 256;
xmlNodePtr *tmp;
int newSize;
tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
ctxt->nodeMax * 2 *
sizeof(ctxt->nodeTab[0]));
newSize = xmlGrowCapacity(ctxt->nodeMax, sizeof(tmp[0]),
10, maxDepth);
if (newSize < 0) {
xmlFatalErrMsgInt(ctxt, XML_ERR_RESOURCE_LIMIT,
"Excessive depth in document: %d,"
" use XML_PARSE_HUGE option\n",
ctxt->nodeNr);
xmlHaltParser(ctxt);
return(-1);
}
tmp = xmlRealloc(ctxt->nodeTab, newSize * sizeof(tmp[0]));
if (tmp == NULL) {
xmlErrMemory(ctxt);
return (-1);
}
ctxt->nodeTab = tmp;
ctxt->nodeMax *= 2;
ctxt->nodeMax = newSize;
}
ctxt->nodeTab[ctxt->nodeNr] = value;
ctxt->node = value;
return (ctxt->nodeNr++);
@ -2148,28 +2164,29 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
xmlStartTag *tag;
if (ctxt->nameNr >= ctxt->nameMax) {
const xmlChar * *tmp;
const xmlChar **tmp;
xmlStartTag *tmp2;
ctxt->nameMax *= 2;
tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
ctxt->nameMax *
sizeof(ctxt->nameTab[0]));
if (tmp == NULL) {
ctxt->nameMax /= 2;
int newSize;
newSize = xmlGrowCapacity(ctxt->nameMax,
sizeof(tmp[0]) + sizeof(tmp2[0]),
10, XML_MAX_ITEMS);
if (newSize < 0)
goto mem_error;
tmp = xmlRealloc(ctxt->nameTab, newSize * sizeof(tmp[0]));
if (tmp == NULL)
goto mem_error;
}
ctxt->nameTab = tmp;
tmp2 = (xmlStartTag *) xmlRealloc((void * *)ctxt->pushTab,
ctxt->nameMax *
sizeof(ctxt->pushTab[0]));
if (tmp2 == NULL) {
ctxt->nameMax /= 2;
tmp2 = xmlRealloc(ctxt->pushTab, newSize * sizeof(tmp2[0]));
if (tmp2 == NULL)
goto mem_error;
}
ctxt->pushTab = tmp2;
ctxt->nameMax = newSize;
} else if (ctxt->pushTab == NULL) {
ctxt->pushTab = (xmlStartTag *) xmlMalloc(ctxt->nameMax *
sizeof(ctxt->pushTab[0]));
ctxt->pushTab = xmlMalloc(ctxt->nameMax * sizeof(ctxt->pushTab[0]));
if (ctxt->pushTab == NULL)
goto mem_error;
}
@ -2229,15 +2246,20 @@ namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
if (ctxt == NULL) return (-1);
if (ctxt->nameNr >= ctxt->nameMax) {
const xmlChar * *tmp;
tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
ctxt->nameMax * 2 *
sizeof(ctxt->nameTab[0]));
if (tmp == NULL) {
const xmlChar **tmp;
int newSize;
newSize = xmlGrowCapacity(ctxt->nameMax, sizeof(tmp[0]),
10, XML_MAX_ITEMS);
if (newSize < 0)
goto mem_error;
tmp = xmlRealloc(ctxt->nameTab, newSize * sizeof(tmp[0]));
if (tmp == NULL)
goto mem_error;
}
ctxt->nameTab = tmp;
ctxt->nameMax *= 2;
ctxt->nameMax = newSize;
}
ctxt->nameTab[ctxt->nameNr] = value;
ctxt->name = value;
@ -2277,16 +2299,23 @@ namePop(xmlParserCtxtPtr ctxt)
static int spacePush(xmlParserCtxtPtr ctxt, int val) {
if (ctxt->spaceNr >= ctxt->spaceMax) {
int *tmp;
int newSize;
ctxt->spaceMax *= 2;
tmp = (int *) xmlRealloc(ctxt->spaceTab,
ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
newSize = xmlGrowCapacity(ctxt->spaceMax, sizeof(tmp[0]),
10, XML_MAX_ITEMS);
if (newSize < 0) {
xmlErrMemory(ctxt);
return(-1);
}
tmp = xmlRealloc(ctxt->spaceTab, newSize * sizeof(tmp[0]));
if (tmp == NULL) {
xmlErrMemory(ctxt);
ctxt->spaceMax /=2;
return(-1);
}
ctxt->spaceTab = tmp;
ctxt->spaceMax = newSize;
}
ctxt->spaceTab[ctxt->spaceNr] = val;
ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
@ -3083,15 +3112,22 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefixOut) {
while ((c != 0) && (c != ':')) { /* tested bigname.xml */
if (len + 10 > max) {
xmlChar *tmp;
int newSize;
max *= 2;
tmp = (xmlChar *) xmlRealloc(buffer, max);
if (tmp == NULL) {
xmlFree(buffer);
newSize = xmlGrowCapacity(max, 1, 1, XML_MAX_ITEMS);
if (newSize < 0) {
xmlErrMemory(ctxt);
xmlFree(buffer);
return(NULL);
}
tmp = xmlRealloc(buffer, newSize);
if (tmp == NULL) {
xmlErrMemory(ctxt);
xmlFree(buffer);
return(NULL);
}
buffer = tmp;
max = newSize;
}
buffer[len++] = c;
c = *cur++;
@ -3171,9 +3207,15 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefixOut) {
while (c != 0) { /* tested bigname2.xml */
if (len + 10 > max) {
xmlChar *tmp;
int newSize;
max *= 2;
tmp = (xmlChar *) xmlRealloc(buffer, max);
newSize = xmlGrowCapacity(max, 1, 1, XML_MAX_ITEMS);
if (newSize < 0) {
xmlErrMemory(ctxt);
xmlFree(buffer);
return(NULL);
}
tmp = xmlRealloc(buffer, newSize);
if (tmp == NULL) {
xmlErrMemory(ctxt);
xmlFree(prefix);
@ -3181,6 +3223,7 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefixOut) {
return(NULL);
}
buffer = tmp;
max = newSize;
}
buffer[len++] = c;
c = *cur++;
@ -3667,24 +3710,26 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
while (xmlIsNameChar(ctxt, c)) {
if (len + 10 > max) {
xmlChar *tmp;
int newSize;
max *= 2;
tmp = (xmlChar *) xmlRealloc(buffer, max);
newSize = xmlGrowCapacity(max, 1, 1, maxLength);
if (newSize < 0) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
xmlFree(buffer);
return(NULL);
}
tmp = xmlRealloc(buffer, newSize);
if (tmp == NULL) {
xmlErrMemory(ctxt);
xmlFree(buffer);
return(NULL);
}
buffer = tmp;
max = newSize;
}
COPY_BUF(buffer, len, c);
cur += l;
c = CUR_SCHAR(cur, l);
if (len > maxLength) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
xmlFree(buffer);
return(NULL);
}
}
buffer[len] = 0;
*str = cur;
@ -3750,22 +3795,24 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
while (xmlIsNameChar(ctxt, c)) {
if (len + 10 > max) {
xmlChar *tmp;
int newSize;
max *= 2;
tmp = (xmlChar *) xmlRealloc(buffer, max);
newSize = xmlGrowCapacity(max, 1, 1, maxLength);
if (newSize < 0) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
xmlFree(buffer);
return(NULL);
}
tmp = xmlRealloc(buffer, newSize);
if (tmp == NULL) {
xmlErrMemory(ctxt);
xmlFree(buffer);
return(NULL);
}
buffer = tmp;
max = newSize;
}
COPY_BUF(buffer, len, c);
if (len > maxLength) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
xmlFree(buffer);
return(NULL);
}
NEXTL(l);
c = xmlCurrentChar(ctxt, &l);
}
@ -4669,22 +4716,24 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
if (len + 5 >= size) {
xmlChar *tmp;
int newSize;
size *= 2;
tmp = (xmlChar *) xmlRealloc(buf, size);
newSize = xmlGrowCapacity(size, 1, 1, maxLength);
if (newSize < 0) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
xmlFree(buf);
return(NULL);
}
tmp = xmlRealloc(buf, newSize);
if (tmp == NULL) {
xmlFree(buf);
xmlErrMemory(ctxt);
return(NULL);
}
buf = tmp;
size = newSize;
}
COPY_BUF(buf, len, cur);
if (len > maxLength) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
xmlFree(buf);
return(NULL);
}
NEXTL(l);
cur = xmlCurrentCharRecover(ctxt, &l);
}
@ -4741,22 +4790,24 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
(PARSER_STOPPED(ctxt) == 0)) { /* checked */
if (len + 1 >= size) {
xmlChar *tmp;
int newSize;
size *= 2;
tmp = (xmlChar *) xmlRealloc(buf, size);
newSize = xmlGrowCapacity(size, 1, 1, maxLength);
if (newSize) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
xmlFree(buf);
return(NULL);
}
tmp = xmlRealloc(buf, size);
if (tmp == NULL) {
xmlErrMemory(ctxt);
xmlFree(buf);
return(NULL);
}
buf = tmp;
size = newSize;
}
buf[len++] = cur;
if (len > maxLength) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
xmlFree(buf);
return(NULL);
}
NEXT;
cur = CUR;
}
@ -5162,9 +5213,9 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
int q, ql;
int r, rl;
int cur, l;
size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
XML_MAX_HUGE_LENGTH :
XML_MAX_TEXT_LENGTH;
int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
XML_MAX_HUGE_LENGTH :
XML_MAX_TEXT_LENGTH;
if (buf == NULL) {
len = 0;
@ -5207,26 +5258,26 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
}
if (len + 5 >= size) {
xmlChar *new_buf;
size_t new_size;
xmlChar *tmp;
int newSize;
new_size = size * 2;
new_buf = (xmlChar *) xmlRealloc(buf, new_size);
if (new_buf == NULL) {
xmlFree (buf);
newSize = xmlGrowCapacity(size, 1, 1, maxLength);
if (newSize < 0) {
xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
"Comment too big found", NULL);
xmlFree (buf);
return;
}
tmp = xmlRealloc(buf, newSize);
if (tmp == NULL) {
xmlErrMemory(ctxt);
xmlFree(buf);
return;
}
buf = new_buf;
size = new_size;
buf = tmp;
size = newSize;
}
COPY_BUF(buf, len, q);
if (len > maxLength) {
xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
"Comment too big found", NULL);
xmlFree (buf);
return;
}
q = r;
ql = rl;
@ -5328,6 +5379,12 @@ get_more:
* save current set of data
*/
if (nbchar > 0) {
if (nbchar > maxLength - len) {
xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
"Comment too big found", NULL);
xmlFree(buf);
return;
}
if (buf == NULL) {
if ((*in == '-') && (in[1] == '-'))
size = nbchar + 1;
@ -5341,11 +5398,11 @@ get_more:
len = 0;
} else if (len + nbchar + 1 >= size) {
xmlChar *new_buf;
size += len + nbchar + XML_PARSER_BUFFER_SIZE;
new_buf = (xmlChar *) xmlRealloc(buf, size);
size += len + nbchar + XML_PARSER_BUFFER_SIZE;
new_buf = xmlRealloc(buf, size);
if (new_buf == NULL) {
xmlFree (buf);
xmlErrMemory(ctxt);
xmlFree(buf);
return;
}
buf = new_buf;
@ -5354,12 +5411,6 @@ get_more:
len += nbchar;
buf[len] = 0;
}
if (len > maxLength) {
xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
"Comment too big found", NULL);
xmlFree (buf);
return;
}
ctxt->input->cur = in;
if (*in == 0xA) {
in++;
@ -5591,23 +5642,25 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
((cur != '?') || (NXT(1) != '>'))) {
if (len + 5 >= size) {
xmlChar *tmp;
size_t new_size = size * 2;
tmp = (xmlChar *) xmlRealloc(buf, new_size);
int newSize;
newSize = xmlGrowCapacity(size, 1, 1, maxLength);
if (newSize < 0) {
xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
"PI %s too big found", target);
xmlFree(buf);
return;
}
tmp = xmlRealloc(buf, newSize);
if (tmp == NULL) {
xmlErrMemory(ctxt);
xmlFree(buf);
return;
}
buf = tmp;
size = new_size;
size = newSize;
}
COPY_BUF(buf, len, cur);
if (len > maxLength) {
xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
"PI %s too big found", target);
xmlFree(buf);
return;
}
NEXTL(l);
cur = xmlCurrentCharRecover(ctxt, &l);
}
@ -7065,15 +7118,23 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
if (inputIdsSize <= depth) {
int *tmp;
int newSize;
inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
tmp = (int *) xmlRealloc(inputIds,
inputIdsSize * sizeof(int));
newSize = xmlGrowCapacity(inputIdsSize, sizeof(tmp[0]),
4, 1000);
if (newSize < 0) {
xmlFatalErrMsg(ctxt, XML_ERR_RESOURCE_LIMIT,
"Maximum conditional section nesting"
" depth exceeded\n");
goto error;
}
tmp = xmlRealloc(inputIds, newSize * sizeof(tmp[0]));
if (tmp == NULL) {
xmlErrMemory(ctxt);
goto error;
}
inputIds = tmp;
inputIdsSize = newSize;
}
inputIds[depth] = id;
depth++;
@ -8499,52 +8560,50 @@ xmlParseStartTag(xmlParserCtxtPtr ctxt) {
for (i = 0; i < nbatts;i += 2) {
if (xmlStrEqual(atts[i], attname)) {
xmlErrAttributeDup(ctxt, NULL, attname);
xmlFree(attvalue);
goto failed;
}
}
/*
* Add the pair to atts
*/
if (atts == NULL) {
maxatts = 22; /* allow for 10 attrs by default */
atts = (const xmlChar **)
xmlMalloc(maxatts * sizeof(xmlChar *));
if (atts == NULL) {
if (nbatts + 4 > maxatts) {
const xmlChar **n;
int newSize;
newSize = xmlGrowCapacity(maxatts, sizeof(n[0]) * 2,
11, XML_MAX_ATTRS);
if (newSize < 0) {
xmlErrMemory(ctxt);
if (attvalue != NULL)
xmlFree(attvalue);
goto failed;
}
ctxt->atts = atts;
ctxt->maxatts = maxatts;
} else if (nbatts + 4 > maxatts) {
const xmlChar **n;
maxatts *= 2;
n = (const xmlChar **) xmlRealloc((void *) atts,
maxatts * sizeof(const xmlChar *));
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if (newSize < 2)
newSize = 2;
#endif
n = xmlRealloc(atts, newSize * sizeof(n[0]) * 2);
if (n == NULL) {
xmlErrMemory(ctxt);
if (attvalue != NULL)
xmlFree(attvalue);
goto failed;
}
atts = n;
maxatts = newSize * 2;
ctxt->atts = atts;
ctxt->maxatts = maxatts;
}
atts[nbatts++] = attname;
atts[nbatts++] = attvalue;
atts[nbatts] = NULL;
atts[nbatts + 1] = NULL;
} else {
if (attvalue != NULL)
xmlFree(attvalue);
attvalue = NULL;
}
failed:
if (attvalue != NULL)
xmlFree(attvalue);
GROW
if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
break;
@ -9250,11 +9309,13 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
* of xmlChar pointers.
*/
if ((atts == NULL) || (nbatts + 5 > maxatts)) {
if (xmlCtxtGrowAttrs(ctxt) < 0) {
goto next_attr;
}
int res = xmlCtxtGrowAttrs(ctxt);
maxatts = ctxt->maxatts;
atts = ctxt->atts;
if (res < 0)
goto next_attr;
}
ctxt->attallocs[nratts++] = (hattname.hashValue & 0x7FFFFFFF) |
((unsigned) alloc << 31);
@ -9325,6 +9386,11 @@ next_attr:
NULL, 1) > 0)
nbNs++;
} else {
if (nratts + nbTotalDef >= XML_MAX_ATTRS) {
xmlFatalErr(ctxt, XML_ERR_RESOURCE_LIMIT,
"Maximum number of attributes exceeded");
break;
}
nbTotalDef += 1;
}
}
@ -9512,12 +9578,15 @@ next_attr:
xmlParserEntityCheck(ctxt, attr->expandedSize);
if ((atts == NULL) || (nbatts + 5 > maxatts)) {
if (xmlCtxtGrowAttrs(ctxt) < 0) {
res = xmlCtxtGrowAttrs(ctxt);
maxatts = ctxt->maxatts;
atts = ctxt->atts;
if (res < 0) {
localname = NULL;
goto done;
}
maxatts = ctxt->maxatts;
atts = ctxt->atts;
}
atts[nbatts++] = attname;
@ -9754,21 +9823,23 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
((r != ']') || (s != ']') || (cur != '>'))) {
if (len + 5 >= size) {
xmlChar *tmp;
int newSize;
tmp = (xmlChar *) xmlRealloc(buf, size * 2);
newSize = xmlGrowCapacity(size, 1, 1, maxLength);
if (newSize < 0) {
xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
"CData section too big found\n");
goto out;
}
tmp = xmlRealloc(buf, newSize);
if (tmp == NULL) {
xmlErrMemory(ctxt);
goto out;
}
buf = tmp;
size *= 2;
size = newSize;
}
COPY_BUF(buf, len, r);
if (len > maxLength) {
xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
"CData section too big found\n");
goto out;
}
r = s;
rl = sl;
s = cur;
@ -10148,6 +10219,9 @@ xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int len = 0;
int size = 10;
int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
XML_MAX_TEXT_LENGTH :
XML_MAX_NAME_LENGTH;
xmlChar cur;
buf = xmlMalloc(size);
@ -10173,15 +10247,22 @@ xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
while ((cur >= '0') && (cur <= '9')) {
if (len + 1 >= size) {
xmlChar *tmp;
int newSize;
size *= 2;
tmp = (xmlChar *) xmlRealloc(buf, size);
newSize = xmlGrowCapacity(size, 1, 1, maxLength);
if (newSize) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "VersionNum");
xmlFree(buf);
return(NULL);
}
tmp = xmlRealloc(buf, newSize);
if (tmp == NULL) {
xmlFree(buf);
xmlErrMemory(ctxt);
xmlFree(buf);
return(NULL);
}
buf = tmp;
size = newSize;
}
buf[len++] = cur;
NEXT;
@ -10281,22 +10362,24 @@ xmlParseEncName(xmlParserCtxtPtr ctxt) {
(cur == '-')) {
if (len + 1 >= size) {
xmlChar *tmp;
int newSize;
size *= 2;
tmp = (xmlChar *) xmlRealloc(buf, size);
newSize = xmlGrowCapacity(size, 1, 1, maxLength);
if (newSize < 0) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "EncName");
xmlFree(buf);
return(NULL);
}
tmp = xmlRealloc(buf, newSize);
if (tmp == NULL) {
xmlErrMemory(ctxt);
xmlFree(buf);
return(NULL);
}
buf = tmp;
size = newSize;
}
buf[len++] = cur;
if (len > maxLength) {
xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "EncName");
xmlFree(buf);
return(NULL);
}
NEXT;
cur = CUR;
}

View File

@ -44,6 +44,7 @@
#include "private/enc.h"
#include "private/error.h"
#include "private/io.h"
#include "private/memory.h"
#include "private/parser.h"
#define XML_MAX_ERRORS 100
@ -3274,29 +3275,23 @@ xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
/* Otherwise, we need to add new node to buffer */
else {
if ((ctxt->node_seq.length + 1 > ctxt->node_seq.maximum) ||
(ctxt->node_seq.buffer == NULL)) {
xmlParserNodeInfo *tmp_buffer;
unsigned int byte_size;
if (ctxt->node_seq.length + 1 > ctxt->node_seq.maximum) {
xmlParserNodeInfo *tmp;
int newSize;
if (ctxt->node_seq.maximum == 0)
ctxt->node_seq.maximum = 2;
byte_size = (sizeof(*ctxt->node_seq.buffer) *
(2 * ctxt->node_seq.maximum));
if (ctxt->node_seq.buffer == NULL)
tmp_buffer = (xmlParserNodeInfo *) xmlMalloc(byte_size);
else
tmp_buffer =
(xmlParserNodeInfo *) xmlRealloc(ctxt->node_seq.buffer,
byte_size);
if (tmp_buffer == NULL) {
newSize = xmlGrowCapacity(ctxt->node_seq.maximum, sizeof(tmp[0]),
4, XML_MAX_ITEMS);
if (newSize < 0) {
xmlCtxtErrMemory(ctxt);
return;
}
ctxt->node_seq.buffer = tmp_buffer;
ctxt->node_seq.maximum *= 2;
tmp = xmlRealloc(ctxt->node_seq.buffer, newSize * sizeof(tmp[0]));
if (tmp == NULL) {
xmlCtxtErrMemory(ctxt);
return;
}
ctxt->node_seq.buffer = tmp;
ctxt->node_seq.maximum = newSize;
}
/* If position is not at end, move elements out of the way */