From 0447275ef8c211e5fee3305cfa83bf13e2922652 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 15 Dec 2024 21:17:07 +0100 Subject: [PATCH] html: Check reallocations for overflow --- HTMLparser.c | 82 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/HTMLparser.c b/HTMLparser.c index 43c5bee3..a95df31f 100644 --- a/HTMLparser.c +++ b/HTMLparser.c @@ -41,10 +41,12 @@ #include "private/error.h" #include "private/html.h" #include "private/io.h" +#include "private/memory.h" #include "private/parser.h" #include "private/tree.h" #define HTML_MAX_NAMELEN 1000 +#define HTML_MAX_ATTRS 100000000 /* 100 million */ #define HTML_PARSER_BIG_BUFFER_SIZE 1000 #define HTML_PARSER_BUFFER_SIZE 100 @@ -158,15 +160,20 @@ htmlnamePush(htmlParserCtxtPtr ctxt, const xmlChar * value) if ((ctxt->html < 10) && (xmlStrEqual(value, BAD_CAST "body"))) ctxt->html = 10; if (ctxt->nameNr >= ctxt->nameMax) { - size_t newSize = ctxt->nameMax * 2; const xmlChar **tmp; + int newSize; - tmp = xmlRealloc((xmlChar **) ctxt->nameTab, - newSize * sizeof(ctxt->nameTab[0])); - if (tmp == NULL) { + newSize = xmlGrowCapacity(ctxt->nameMax, sizeof(tmp[0]), + 10, XML_MAX_ITEMS); + if (newSize < 0) { htmlErrMemory(ctxt); return (-1); } + tmp = xmlRealloc(ctxt->nameTab, newSize * sizeof(tmp[0])); + if (tmp == NULL) { + htmlErrMemory(ctxt); + return(-1); + } ctxt->nameTab = tmp; ctxt->nameMax = newSize; } @@ -214,17 +221,22 @@ static int htmlNodeInfoPush(htmlParserCtxtPtr ctxt, htmlParserNodeInfo *value) { if (ctxt->nodeInfoNr >= ctxt->nodeInfoMax) { - if (ctxt->nodeInfoMax == 0) - ctxt->nodeInfoMax = 5; - ctxt->nodeInfoMax *= 2; - ctxt->nodeInfoTab = (htmlParserNodeInfo *) - xmlRealloc((htmlParserNodeInfo *)ctxt->nodeInfoTab, - ctxt->nodeInfoMax * - sizeof(ctxt->nodeInfoTab[0])); - if (ctxt->nodeInfoTab == NULL) { + xmlParserNodeInfo *tmp; + int newSize; + + newSize = xmlGrowCapacity(ctxt->nodeInfoMax, sizeof(tmp[0]), + 5, XML_MAX_ITEMS); + if (newSize < 0) { htmlErrMemory(ctxt); return (0); } + tmp = xmlRealloc(ctxt->nodeInfoTab, newSize * sizeof(tmp[0])); + if (tmp == NULL) { + htmlErrMemory(ctxt); + return (0); + } + ctxt->nodeInfoTab = tmp; + ctxt->nodeInfoMax = newSize; } ctxt->nodeInfoTab[ctxt->nodeInfoNr] = *value; ctxt->nodeInfo = &ctxt->nodeInfoTab[ctxt->nodeInfoNr]; @@ -2835,7 +2847,7 @@ next_chunk: if (extraSize > buffer_size - used) { size_t newSize = (used + extraSize) * 2; - xmlChar *tmp = (xmlChar *) xmlRealloc(buffer, newSize + 1); + xmlChar *tmp = xmlRealloc(buffer, newSize + 1); if (tmp == NULL) { htmlErrMemory(ctxt); @@ -3804,47 +3816,49 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) { if (nbatts + 4 > maxatts) { const xmlChar **tmp; unsigned *utmp; - size_t newSize = maxatts ? maxatts * 2 : 22; + int newSize; - tmp = xmlMalloc(newSize * sizeof(tmp[0])); + newSize = xmlGrowCapacity(maxatts, + sizeof(tmp[0]) * 2 + sizeof(utmp[0]), + 11, HTML_MAX_ATTRS); + if (newSize < 0) { + htmlErrMemory(ctxt); + goto failed; + } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (newSize < 2) + newSize = 2; +#endif + tmp = xmlRealloc(atts, newSize * sizeof(tmp[0]) * 2); if (tmp == NULL) { htmlErrMemory(ctxt); - if (attvalue != NULL) - xmlFree(attvalue); goto failed; } + atts = tmp; + ctxt->atts = tmp; - utmp = xmlRealloc(ctxt->attallocs, - newSize / 2 * sizeof(utmp[0])); + utmp = xmlRealloc(ctxt->attallocs, newSize * sizeof(utmp[0])); if (utmp == NULL) { htmlErrMemory(ctxt); - if (attvalue != NULL) - xmlFree(attvalue); - xmlFree(tmp); goto failed; } - - if (maxatts > 0) - memcpy(tmp, atts, maxatts * sizeof(tmp[0])); - xmlFree(atts); - - atts = tmp; - maxatts = newSize; - ctxt->atts = atts; ctxt->attallocs = utmp; + + maxatts = newSize * 2; ctxt->maxatts = maxatts; } ctxt->attallocs[nbatts/2] = hattname.hashValue; atts[nbatts++] = attname; atts[nbatts++] = attvalue; - } - else { - if (attvalue != NULL) - xmlFree(attvalue); + + attvalue = NULL; } failed: + if (attvalue != NULL) + xmlFree(attvalue); + SKIP_BLANKS; }