| 
							
							
							
						 |  |  | @@ -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 */ | 
		
	
	
		
			
				
					
					|  |  |  |   |