mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-21 21:18:35 +01:00
#3527: Upgrade bundled expat to 2.4.5
This commit is contained in:
parent
00d5e7171a
commit
02abb70601
@ -1041,7 +1041,7 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold(
|
||||
*/
|
||||
#define XML_MAJOR_VERSION 2
|
||||
#define XML_MINOR_VERSION 4
|
||||
#define XML_MICRO_VERSION 4
|
||||
#define XML_MICRO_VERSION 5
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* 2e2c8ce5f11a473d65ec313ab20ceee6afefb355f5405afc06e7204e2e41c8c0 (2.4.4+)
|
||||
/* 042615face2b8727e23bb27cf4f56baa292a1f91df47c1bca8f09dff49067888 (2.4.5+)
|
||||
__ __ _
|
||||
___\ \/ /_ __ __ _| |_
|
||||
/ _ \\ /| '_ \ / _` | __|
|
||||
@ -11,9 +11,9 @@
|
||||
Copyright (c) 2000-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2005-2009 Steven Solie <ssolie@users.sourceforge.net>
|
||||
Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2016 Eric Rahm <erahm@mozilla.com>
|
||||
Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016 Gaurav <g.gupta@samsung.com>
|
||||
Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
|
||||
Copyright (c) 2016 Gustavo Grieco <gustavo.grieco@imag.fr>
|
||||
@ -727,8 +727,7 @@ XML_ParserCreate(const XML_Char *encodingName) {
|
||||
|
||||
XML_Parser XMLCALL
|
||||
XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
|
||||
XML_Char tmp[2];
|
||||
*tmp = nsSep;
|
||||
XML_Char tmp[2] = {nsSep, 0};
|
||||
return XML_ParserCreate_MM(encodingName, NULL, tmp);
|
||||
}
|
||||
|
||||
@ -1364,8 +1363,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
|
||||
would be otherwise.
|
||||
*/
|
||||
if (parser->m_ns) {
|
||||
XML_Char tmp[2];
|
||||
*tmp = parser->m_namespaceSeparator;
|
||||
XML_Char tmp[2] = {parser->m_namespaceSeparator, 0};
|
||||
parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
|
||||
} else {
|
||||
parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
|
||||
@ -2509,29 +2507,29 @@ XML_GetFeatureList(void) {
|
||||
{XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
|
||||
sizeof(XML_LChar)},
|
||||
#ifdef XML_UNICODE
|
||||
{XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
|
||||
{XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
|
||||
#endif
|
||||
#ifdef XML_UNICODE_WCHAR_T
|
||||
{XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
|
||||
{XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
|
||||
#endif
|
||||
#ifdef XML_DTD
|
||||
{XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
|
||||
{XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
|
||||
#endif
|
||||
#ifdef XML_CONTEXT_BYTES
|
||||
{XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
|
||||
XML_CONTEXT_BYTES},
|
||||
{XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
|
||||
XML_CONTEXT_BYTES},
|
||||
#endif
|
||||
#ifdef XML_MIN_SIZE
|
||||
{XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
|
||||
{XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
|
||||
#endif
|
||||
#ifdef XML_NS
|
||||
{XML_FEATURE_NS, XML_L("XML_NS"), 0},
|
||||
{XML_FEATURE_NS, XML_L("XML_NS"), 0},
|
||||
#endif
|
||||
#ifdef XML_LARGE_SIZE
|
||||
{XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
|
||||
{XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
|
||||
#endif
|
||||
#ifdef XML_ATTR_INFO
|
||||
{XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
|
||||
{XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
|
||||
#endif
|
||||
#ifdef XML_DTD
|
||||
/* Added in Expat 2.4.0. */
|
||||
@ -2543,7 +2541,7 @@ XML_GetFeatureList(void) {
|
||||
XML_L("XML_BLAP_ACT_THRES"),
|
||||
EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
|
||||
#endif
|
||||
{XML_FEATURE_END, NULL, 0}};
|
||||
{XML_FEATURE_END, NULL, 0}};
|
||||
|
||||
return features;
|
||||
}
|
||||
@ -2583,6 +2581,7 @@ storeRawNames(XML_Parser parser) {
|
||||
while (tag) {
|
||||
int bufSize;
|
||||
int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
|
||||
size_t rawNameLen;
|
||||
char *rawNameBuf = tag->buf + nameLen;
|
||||
/* Stop if already stored. Since m_tagStack is a stack, we can stop
|
||||
at the first entry that has already been copied; everything
|
||||
@ -2594,7 +2593,11 @@ storeRawNames(XML_Parser parser) {
|
||||
/* For re-use purposes we need to ensure that the
|
||||
size of tag->buf is a multiple of sizeof(XML_Char).
|
||||
*/
|
||||
bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
|
||||
rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
|
||||
/* Detect and prevent integer overflow. */
|
||||
if (rawNameLen > (size_t)INT_MAX - nameLen)
|
||||
return XML_FALSE;
|
||||
bufSize = nameLen + (int)rawNameLen;
|
||||
if (bufSize > tag->bufEnd - tag->buf) {
|
||||
char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
|
||||
if (temp == NULL)
|
||||
@ -3287,13 +3290,38 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
|
||||
/* get the attributes from the tokenizer */
|
||||
n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
|
||||
|
||||
/* Detect and prevent integer overflow */
|
||||
if (n > INT_MAX - nDefaultAtts) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (n + nDefaultAtts > parser->m_attsSize) {
|
||||
int oldAttsSize = parser->m_attsSize;
|
||||
ATTRIBUTE *temp;
|
||||
#ifdef XML_ATTR_INFO
|
||||
XML_AttrInfo *temp2;
|
||||
#endif
|
||||
|
||||
/* Detect and prevent integer overflow */
|
||||
if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
|
||||
|| (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
|
||||
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) {
|
||||
parser->m_attsSize = oldAttsSize;
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
|
||||
parser->m_attsSize * sizeof(ATTRIBUTE));
|
||||
if (temp == NULL) {
|
||||
@ -3302,6 +3330,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
}
|
||||
parser->m_atts = temp;
|
||||
#ifdef XML_ATTR_INFO
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
# if UINT_MAX >= SIZE_MAX
|
||||
if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) {
|
||||
parser->m_attsSize = oldAttsSize;
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
# endif
|
||||
|
||||
temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
|
||||
parser->m_attsSize * sizeof(XML_AttrInfo));
|
||||
if (temp2 == NULL) {
|
||||
@ -3440,7 +3479,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
if (nPrefixes) {
|
||||
int j; /* hash table index */
|
||||
unsigned long version = parser->m_nsAttsVersion;
|
||||
int nsAttsSize = (int)1 << parser->m_nsAttsPower;
|
||||
|
||||
/* Detect and prevent invalid shift */
|
||||
if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
|
||||
unsigned char oldNsAttsPower = parser->m_nsAttsPower;
|
||||
/* size of hash table must be at least 2 * (# of prefixed attributes) */
|
||||
if ((nPrefixes << 1)
|
||||
@ -3451,7 +3496,28 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
;
|
||||
if (parser->m_nsAttsPower < 3)
|
||||
parser->m_nsAttsPower = 3;
|
||||
nsAttsSize = (int)1 << parser->m_nsAttsPower;
|
||||
|
||||
/* Detect and prevent invalid shift */
|
||||
if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
|
||||
/* Restore actual size of memory in m_nsAtts */
|
||||
parser->m_nsAttsPower = oldNsAttsPower;
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
nsAttsSize = 1u << parser->m_nsAttsPower;
|
||||
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
|
||||
/* Restore actual size of memory in m_nsAtts */
|
||||
parser->m_nsAttsPower = oldNsAttsPower;
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
|
||||
nsAttsSize * sizeof(NS_ATT));
|
||||
if (! temp) {
|
||||
@ -3609,9 +3675,31 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
|
||||
tagNamePtr->prefixLen = prefixLen;
|
||||
for (i = 0; localPart[i++];)
|
||||
; /* i includes null terminator */
|
||||
|
||||
/* Detect and prevent integer overflow */
|
||||
if (binding->uriLen > INT_MAX - prefixLen
|
||||
|| i > INT_MAX - (binding->uriLen + prefixLen)) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
n = i + binding->uriLen + prefixLen;
|
||||
if (n > binding->uriAlloc) {
|
||||
TAG *p;
|
||||
|
||||
/* Detect and prevent integer overflow */
|
||||
if (n > INT_MAX - EXPAND_SPARE) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
#endif
|
||||
|
||||
uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
|
||||
if (! uri)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
@ -3691,6 +3779,17 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
|
||||
if (! mustBeXML && isXMLNS
|
||||
&& (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
|
||||
isXMLNS = XML_FALSE;
|
||||
|
||||
// NOTE: While Expat does not validate namespace URIs against RFC 3986,
|
||||
// we have to at least make sure that the XML processor on top of
|
||||
// Expat (that is splitting tag names by namespace separator into
|
||||
// 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused
|
||||
// by an attacker putting additional namespace separator characters
|
||||
// into namespace declarations. That would be ambiguous and not to
|
||||
// be expected.
|
||||
if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) {
|
||||
return XML_ERROR_SYNTAX;
|
||||
}
|
||||
}
|
||||
isXML = isXML && len == xmlLen;
|
||||
isXMLNS = isXMLNS && len == xmlnsLen;
|
||||
@ -3707,6 +3806,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
|
||||
if (parser->m_freeBindingList) {
|
||||
b = parser->m_freeBindingList;
|
||||
if (len > b->uriAlloc) {
|
||||
/* Detect and prevent integer overflow */
|
||||
if (len > INT_MAX - EXPAND_SPARE) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
#endif
|
||||
|
||||
XML_Char *temp = (XML_Char *)REALLOC(
|
||||
parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
|
||||
if (temp == NULL)
|
||||
@ -3719,6 +3833,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
|
||||
b = (BINDING *)MALLOC(parser, sizeof(BINDING));
|
||||
if (! b)
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
|
||||
/* Detect and prevent integer overflow */
|
||||
if (len > INT_MAX - EXPAND_SPARE) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
#endif
|
||||
|
||||
b->uri
|
||||
= (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
|
||||
if (! b->uri) {
|
||||
@ -5045,6 +5174,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
if (parser->m_prologState.level >= parser->m_groupSize) {
|
||||
if (parser->m_groupSize) {
|
||||
{
|
||||
/* Detect and prevent integer overflow */
|
||||
if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
char *const new_connector = (char *)REALLOC(
|
||||
parser, parser->m_groupConnector, parser->m_groupSize *= 2);
|
||||
if (new_connector == NULL) {
|
||||
@ -5055,6 +5189,16 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
|
||||
}
|
||||
|
||||
if (dtd->scaffIndex) {
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
|
||||
return XML_ERROR_NO_MEMORY;
|
||||
}
|
||||
#endif
|
||||
|
||||
int *const new_scaff_index = (int *)REALLOC(
|
||||
parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
|
||||
if (new_scaff_index == NULL)
|
||||
@ -6131,7 +6275,24 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
|
||||
}
|
||||
} else {
|
||||
DEFAULT_ATTRIBUTE *temp;
|
||||
|
||||
/* Detect and prevent integer overflow */
|
||||
if (type->allocDefaultAtts > INT_MAX / 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = type->allocDefaultAtts * 2;
|
||||
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
|
||||
(count * sizeof(DEFAULT_ATTRIBUTE)));
|
||||
if (temp == NULL)
|
||||
@ -6594,8 +6755,8 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
|
||||
if (! newE)
|
||||
return 0;
|
||||
if (oldE->nDefaultAtts) {
|
||||
newE->defaultAtts = (DEFAULT_ATTRIBUTE *)ms->malloc_fcn(
|
||||
oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
|
||||
newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
|
||||
ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
|
||||
if (! newE->defaultAtts) {
|
||||
return 0;
|
||||
}
|
||||
@ -6782,8 +6943,20 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
|
||||
/* check for overflow (table is half full) */
|
||||
if (table->used >> (table->power - 1)) {
|
||||
unsigned char newPower = table->power + 1;
|
||||
|
||||
/* Detect and prevent invalid shift */
|
||||
if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t newSize = (size_t)1 << newPower;
|
||||
unsigned long newMask = (unsigned long)newSize - 1;
|
||||
|
||||
/* Detect and prevent integer overflow */
|
||||
if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t tsize = newSize * sizeof(NAMED *);
|
||||
NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
|
||||
if (! newV)
|
||||
@ -7133,6 +7306,20 @@ nextScaffoldPart(XML_Parser parser) {
|
||||
if (dtd->scaffCount >= dtd->scaffSize) {
|
||||
CONTENT_SCAFFOLD *temp;
|
||||
if (dtd->scaffold) {
|
||||
/* Detect and prevent integer overflow */
|
||||
if (dtd->scaffSize > UINT_MAX / 2u) {
|
||||
return -1;
|
||||
}
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
temp = (CONTENT_SCAFFOLD *)REALLOC(
|
||||
parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
|
||||
if (temp == NULL)
|
||||
@ -7164,55 +7351,115 @@ nextScaffoldPart(XML_Parser parser) {
|
||||
return next;
|
||||
}
|
||||
|
||||
static void
|
||||
build_node(XML_Parser parser, int src_node, XML_Content *dest,
|
||||
XML_Content **contpos, XML_Char **strpos) {
|
||||
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
|
||||
dest->type = dtd->scaffold[src_node].type;
|
||||
dest->quant = dtd->scaffold[src_node].quant;
|
||||
if (dest->type == XML_CTYPE_NAME) {
|
||||
const XML_Char *src;
|
||||
dest->name = *strpos;
|
||||
src = dtd->scaffold[src_node].name;
|
||||
for (;;) {
|
||||
*(*strpos)++ = *src;
|
||||
if (! *src)
|
||||
break;
|
||||
src++;
|
||||
}
|
||||
dest->numchildren = 0;
|
||||
dest->children = NULL;
|
||||
} else {
|
||||
unsigned int i;
|
||||
int cn;
|
||||
dest->numchildren = dtd->scaffold[src_node].childcnt;
|
||||
dest->children = *contpos;
|
||||
*contpos += dest->numchildren;
|
||||
for (i = 0, cn = dtd->scaffold[src_node].firstchild; i < dest->numchildren;
|
||||
i++, cn = dtd->scaffold[cn].nextsib) {
|
||||
build_node(parser, cn, &(dest->children[i]), contpos, strpos);
|
||||
}
|
||||
dest->name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static XML_Content *
|
||||
build_model(XML_Parser parser) {
|
||||
/* Function build_model transforms the existing parser->m_dtd->scaffold
|
||||
* array of CONTENT_SCAFFOLD tree nodes into a new array of
|
||||
* XML_Content tree nodes followed by a gapless list of zero-terminated
|
||||
* strings. */
|
||||
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
|
||||
XML_Content *ret;
|
||||
XML_Content *cpos;
|
||||
XML_Char *str;
|
||||
int allocsize = (dtd->scaffCount * sizeof(XML_Content)
|
||||
+ (dtd->contentStringLen * sizeof(XML_Char)));
|
||||
XML_Char *str; /* the current string writing location */
|
||||
|
||||
/* Detect and prevent integer overflow.
|
||||
* The preprocessor guard addresses the "always false" warning
|
||||
* from -Wtype-limits on platforms where
|
||||
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
|
||||
#if UINT_MAX >= SIZE_MAX
|
||||
if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) {
|
||||
return NULL;
|
||||
}
|
||||
if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (dtd->scaffCount * sizeof(XML_Content)
|
||||
> (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
|
||||
+ (dtd->contentStringLen * sizeof(XML_Char)));
|
||||
|
||||
ret = (XML_Content *)MALLOC(parser, allocsize);
|
||||
if (! ret)
|
||||
return NULL;
|
||||
|
||||
str = (XML_Char *)(&ret[dtd->scaffCount]);
|
||||
cpos = &ret[1];
|
||||
/* What follows is an iterative implementation (of what was previously done
|
||||
* recursively in a dedicated function called "build_node". The old recursive
|
||||
* build_node could be forced into stack exhaustion from input as small as a
|
||||
* few megabyte, and so that was a security issue. Hence, a function call
|
||||
* stack is avoided now by resolving recursion.)
|
||||
*
|
||||
* The iterative approach works as follows:
|
||||
*
|
||||
* - We use space in the target array for building a temporary stack structure
|
||||
* while that space is still unused.
|
||||
* The stack grows from the array's end downwards and the "actual data"
|
||||
* grows from the start upwards, sequentially.
|
||||
* (Because stack grows downwards, pushing onto the stack is a decrement
|
||||
* while popping off the stack is an increment.)
|
||||
*
|
||||
* - A stack element appears as a regular XML_Content node on the outside,
|
||||
* but only uses a single field -- numchildren -- to store the source
|
||||
* tree node array index. These are the breadcrumbs leading the way back
|
||||
* during pre-order (node first) depth-first traversal.
|
||||
*
|
||||
* - The reason we know the stack will never grow into (or overlap with)
|
||||
* the area with data of value at the start of the array is because
|
||||
* the overall number of elements to process matches the size of the array,
|
||||
* and the sum of fully processed nodes and yet-to-be processed nodes
|
||||
* on the stack, cannot be more than the total number of nodes.
|
||||
* It is possible for the top of the stack and the about-to-write node
|
||||
* to meet, but that is safe because we get the source index out
|
||||
* before doing any writes on that node.
|
||||
*/
|
||||
XML_Content *dest = ret; /* tree node writing location, moves upwards */
|
||||
XML_Content *const destLimit = &ret[dtd->scaffCount];
|
||||
XML_Content *const stackBottom = &ret[dtd->scaffCount];
|
||||
XML_Content *stackTop = stackBottom; /* i.e. stack is initially empty */
|
||||
str = (XML_Char *)&ret[dtd->scaffCount];
|
||||
|
||||
/* Push source tree root node index onto the stack */
|
||||
(--stackTop)->numchildren = 0;
|
||||
|
||||
for (; dest < destLimit; dest++) {
|
||||
/* Pop source tree node index off the stack */
|
||||
const int src_node = (int)(stackTop++)->numchildren;
|
||||
|
||||
/* Convert item */
|
||||
dest->type = dtd->scaffold[src_node].type;
|
||||
dest->quant = dtd->scaffold[src_node].quant;
|
||||
if (dest->type == XML_CTYPE_NAME) {
|
||||
const XML_Char *src;
|
||||
dest->name = str;
|
||||
src = dtd->scaffold[src_node].name;
|
||||
for (;;) {
|
||||
*str++ = *src;
|
||||
if (! *src)
|
||||
break;
|
||||
src++;
|
||||
}
|
||||
dest->numchildren = 0;
|
||||
dest->children = NULL;
|
||||
} else {
|
||||
unsigned int i;
|
||||
int cn;
|
||||
dest->name = NULL;
|
||||
dest->numchildren = dtd->scaffold[src_node].childcnt;
|
||||
dest->children = &dest[1];
|
||||
|
||||
/* Push children to the stack
|
||||
* in a way where the first child ends up at the top of the
|
||||
* (downwards growing) stack, in order to be processed first. */
|
||||
stackTop -= dest->numchildren;
|
||||
for (i = 0, cn = dtd->scaffold[src_node].firstchild;
|
||||
i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) {
|
||||
(stackTop + i)->numchildren = (unsigned int)cn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
build_node(parser, 0, ret, &cpos, &str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -7241,7 +7488,7 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
|
||||
|
||||
static XML_Char *
|
||||
copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
|
||||
int charsRequired = 0;
|
||||
size_t charsRequired = 0;
|
||||
XML_Char *result;
|
||||
|
||||
/* First determine how long the string is */
|
||||
|
@ -11,10 +11,11 @@
|
||||
Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2005-2009 Steven Solie <ssolie@users.sourceforge.net>
|
||||
Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
|
||||
Copyright (c) 2021 Dong-hee Na <donghee.na@python.org>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -11,8 +11,8 @@
|
||||
Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2002 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2005-2009 Steven Solie <ssolie@users.sourceforge.net>
|
||||
Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2005-2009 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016 Pascal Cuoq <cuoq@trust-in-soft.com>
|
||||
Copyright (c) 2016 Don Lewis <truckman@apache.org>
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
@ -20,6 +20,7 @@
|
||||
Copyright (c) 2017 Benbuck Nason <bnason@netflix.com>
|
||||
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
|
||||
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
|
||||
Copyright (c) 2021 Dong-hee Na <donghee.na@python.org>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@ -97,11 +98,6 @@
|
||||
+ ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \
|
||||
& (1u << (((byte)[2]) & 0x1F)))
|
||||
|
||||
#define UTF8_GET_NAMING(pages, p, n) \
|
||||
((n) == 2 \
|
||||
? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
|
||||
: ((n) == 3 ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) : 0))
|
||||
|
||||
/* Detection of invalid UTF-8 sequences is based on Table 3.1B
|
||||
of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/
|
||||
with the additional restriction of not allowing the Unicode
|
||||
@ -276,8 +272,8 @@ sb_byteToAscii(const ENCODING *enc, const char *p) {
|
||||
(AS_NORMAL_ENCODING(enc)->isInvalid##n \
|
||||
&& AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
|
||||
#else
|
||||
#define IS_INVALID_CHAR(enc, p, n) \
|
||||
(AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
|
||||
# define IS_INVALID_CHAR(enc, p, n) \
|
||||
(AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
|
||||
#endif
|
||||
|
||||
#ifdef XML_MIN_SIZE
|
||||
|
@ -10,7 +10,7 @@
|
||||
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
|
||||
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2016-2021 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2018 Benjamin Peterson <benjamin@python.org>
|
||||
Copyright (c) 2018 Anton Maklakov <antmak.pub@gmail.com>
|
||||
@ -69,7 +69,7 @@
|
||||
case BT_LEAD##n: \
|
||||
if (end - ptr < n) \
|
||||
return XML_TOK_PARTIAL_CHAR; \
|
||||
if (! IS_NAME_CHAR(enc, ptr, n)) { \
|
||||
if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NAME_CHAR(enc, ptr, n)) { \
|
||||
*nextTokPtr = ptr; \
|
||||
return XML_TOK_INVALID; \
|
||||
} \
|
||||
@ -98,7 +98,7 @@
|
||||
case BT_LEAD##n: \
|
||||
if (end - ptr < n) \
|
||||
return XML_TOK_PARTIAL_CHAR; \
|
||||
if (! IS_NMSTRT_CHAR(enc, ptr, n)) { \
|
||||
if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \
|
||||
*nextTokPtr = ptr; \
|
||||
return XML_TOK_INVALID; \
|
||||
} \
|
||||
@ -1142,6 +1142,10 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
|
||||
case BT_LEAD##n: \
|
||||
if (end - ptr < n) \
|
||||
return XML_TOK_PARTIAL_CHAR; \
|
||||
if (IS_INVALID_CHAR(enc, ptr, n)) { \
|
||||
*nextTokPtr = ptr; \
|
||||
return XML_TOK_INVALID; \
|
||||
} \
|
||||
if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
|
||||
ptr += n; \
|
||||
tok = XML_TOK_NAME; \
|
||||
@ -1270,7 +1274,7 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
|
||||
switch (BYTE_TYPE(enc, ptr)) {
|
||||
# define LEAD_CASE(n) \
|
||||
case BT_LEAD##n: \
|
||||
ptr += n; \
|
||||
ptr += n; /* NOTE: The encoding has already been validated. */ \
|
||||
break;
|
||||
LEAD_CASE(2)
|
||||
LEAD_CASE(3)
|
||||
@ -1339,7 +1343,7 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
|
||||
switch (BYTE_TYPE(enc, ptr)) {
|
||||
# define LEAD_CASE(n) \
|
||||
case BT_LEAD##n: \
|
||||
ptr += n; \
|
||||
ptr += n; /* NOTE: The encoding has already been validated. */ \
|
||||
break;
|
||||
LEAD_CASE(2)
|
||||
LEAD_CASE(3)
|
||||
@ -1518,7 +1522,7 @@ PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
|
||||
state = inName; \
|
||||
}
|
||||
# define LEAD_CASE(n) \
|
||||
case BT_LEAD##n: \
|
||||
case BT_LEAD##n: /* NOTE: The encoding has already been validated. */ \
|
||||
START_NAME ptr += (n - MINBPC(enc)); \
|
||||
break;
|
||||
LEAD_CASE(2)
|
||||
@ -1730,7 +1734,7 @@ PREFIX(nameLength)(const ENCODING *enc, const char *ptr) {
|
||||
switch (BYTE_TYPE(enc, ptr)) {
|
||||
# define LEAD_CASE(n) \
|
||||
case BT_LEAD##n: \
|
||||
ptr += n; \
|
||||
ptr += n; /* NOTE: The encoding has already been validated. */ \
|
||||
break;
|
||||
LEAD_CASE(2)
|
||||
LEAD_CASE(3)
|
||||
@ -1775,7 +1779,7 @@ PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end,
|
||||
switch (BYTE_TYPE(enc, ptr)) {
|
||||
# define LEAD_CASE(n) \
|
||||
case BT_LEAD##n: \
|
||||
ptr += n; \
|
||||
ptr += n; /* NOTE: The encoding has already been validated. */ \
|
||||
pos->columnNumber++; \
|
||||
break;
|
||||
LEAD_CASE(2)
|
||||
|
Loading…
x
Reference in New Issue
Block a user