diff options
author | Tobias Markmann <tm@ayena.de> | 2017-06-20 12:17:48 (GMT) |
---|---|---|
committer | Tobias Markmann <tm@ayena.de> | 2017-06-20 14:43:05 (GMT) |
commit | a507a88a189bb603c9f2d686c9c8dafca49c053d (patch) | |
tree | ac32d8281fdefb83f3a0d9ef79c3983d98bed24d /3rdParty/Expat/src/xmlparse.c | |
parent | b807e3fa975cf25e5e901b59643419a5a73a12fe (diff) | |
download | swift-a507a88a189bb603c9f2d686c9c8dafca49c053d.zip swift-a507a88a189bb603c9f2d686c9c8dafca49c053d.tar.bz2 |
Update 3rdParty/Expat to version 2.2.1
Test-Information:
Build successfully on macOS 10.12.5 with clang trunk and
./scons test=all try_libxml=no try_expat=no .
Change-Id: I0cc0680086ea40f92bbfa7296d10beb08cc657e3
Diffstat (limited to '3rdParty/Expat/src/xmlparse.c')
-rw-r--r-- | 3rdParty/Expat/src/xmlparse.c | 734 |
1 files changed, 579 insertions, 155 deletions
diff --git a/3rdParty/Expat/src/xmlparse.c b/3rdParty/Expat/src/xmlparse.c index 9b8bd69..76f078e 100644 --- a/3rdParty/Expat/src/xmlparse.c +++ b/3rdParty/Expat/src/xmlparse.c @@ -2,4 +2,8 @@ See the file COPYING for copying permission. + + 77fea421d361dca90041d0040ecf1dca651167fadf2af79e990e35168d70d933 (2.2.1+) */ +#define _GNU_SOURCE /* syscall prototype */ + #include <stddef.h> @@ -8,3 +12,12 @@ #include <limits.h> /* UINT_MAX */ -#include <time.h> /* time() */ +#include <stdio.h> /* fprintf */ +#include <stdlib.h> /* getenv */ + +#ifdef _WIN32 +#define getpid GetCurrentProcessId +#else +#include <sys/time.h> /* gettimeofday() */ +#include <sys/types.h> /* getpid() */ +#include <unistd.h> /* getpid() */ +#endif @@ -12,13 +25,7 @@ -#ifdef COMPILED_FROM_DSP +#ifdef _WIN32 #include "winconfig.h" -#elif defined(MACOS_CLASSIC) -#include "macconfig.h" -#elif defined(__amigaos__) -#include "amigaconfig.h" -#elif defined(__WATCOMC__) -#include "watcomconfig.h" #elif defined(HAVE_EXPAT_CONFIG_H) #include <expat_config.h> -#endif /* ndef COMPILED_FROM_DSP */ +#endif /* ndef _WIN32 */ @@ -26,2 +33,3 @@ #include "expat.h" +#include "siphash.h" @@ -104,13 +112,7 @@ typedef struct { -/* Basic character hash algorithm, taken from Python's string hash: - h = h * 1000003 ^ character, the constant being a prime number. +static size_t +keylen(KEY s); -*/ -#ifdef XML_UNICODE -#define CHAR_HASH(h, c) \ - (((h) * 0xF4243) ^ (unsigned short)(c)) -#else -#define CHAR_HASH(h, c) \ - (((h) * 0xF4243) ^ (unsigned char)(c)) -#endif +static void +copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key); @@ -350,2 +352,4 @@ doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, +static void +freeBindings(XML_Parser parser, BINDING *bindings); static enum XML_Error @@ -434,3 +438,3 @@ getElementType(XML_Parser parser, const ENCODING *enc, -static unsigned long generate_hash_secret_salt(void); +static unsigned long generate_hash_secret_salt(XML_Parser parser); static XML_Bool startParsing(XML_Parser parser); @@ -692,8 +696,151 @@ static const XML_Char implicitContext[] = { + +#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) +# include <errno.h> + +# if defined(HAVE_GETRANDOM) +# include <sys/random.h> /* getrandom */ +# else +# include <unistd.h> /* syscall */ +# include <sys/syscall.h> /* SYS_getrandom */ +# endif + +/* Obtain entropy on Linux 3.17+ */ +static int +writeRandomBytes_getrandom(void * target, size_t count) { + int success = 0; /* full count bytes written? */ + size_t bytesWrittenTotal = 0; + const unsigned int getrandomFlags = 0; + + do { + void * const currentTarget = (void*)((char*)target + bytesWrittenTotal); + const size_t bytesToWrite = count - bytesWrittenTotal; + + const int bytesWrittenMore = +#if defined(HAVE_GETRANDOM) + getrandom(currentTarget, bytesToWrite, getrandomFlags); +#else + syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags); +#endif + + if (bytesWrittenMore > 0) { + bytesWrittenTotal += bytesWrittenMore; + if (bytesWrittenTotal >= count) + success = 1; + } + } while (! success && (errno == EINTR || errno == EAGAIN)); + + return success; +} + +#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ + + +#ifdef _WIN32 + +typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG); + +/* Obtain entropy on Windows XP / Windows Server 2003 and later. + * Hint on RtlGenRandom and the following article from libsodioum. + * + * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI + * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/ + */ +static int +writeRandomBytes_RtlGenRandom(void * target, size_t count) { + int success = 0; /* full count bytes written? */ + const HMODULE advapi32 = LoadLibrary("ADVAPI32.DLL"); + + if (advapi32) { + const RTLGENRANDOM_FUNC RtlGenRandom + = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036"); + if (RtlGenRandom) { + if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) { + success = 1; + } + } + FreeLibrary(advapi32); + } + + return success; +} + +#endif /* _WIN32 */ + + static unsigned long -generate_hash_secret_salt(void) +gather_time_entropy(void) { - unsigned int seed = time(NULL) % UINT_MAX; - srand(seed); - return rand(); +#ifdef _WIN32 + FILETIME ft; + GetSystemTimeAsFileTime(&ft); /* never fails */ + return ft.dwHighDateTime ^ ft.dwLowDateTime; +#else + struct timeval tv; + int gettimeofday_res; + + gettimeofday_res = gettimeofday(&tv, NULL); + assert (gettimeofday_res == 0); + + /* Microseconds time is <20 bits entropy */ + return tv.tv_usec; +#endif +} + +#if defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_LIBBSD) +# include <bsd/stdlib.h> +#endif + +static unsigned long +ENTROPY_DEBUG(const char * label, unsigned long entropy) { + const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG"); + if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) { + fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", + label, + (int)sizeof(entropy) * 2, entropy, + (unsigned long)sizeof(entropy)); + } + return entropy; +} + +static unsigned long +generate_hash_secret_salt(XML_Parser parser) +{ + unsigned long entropy; + (void)parser; +#if defined(HAVE_ARC4RANDOM_BUF) || defined(__CloudABI__) + (void)gather_time_entropy; + arc4random_buf(&entropy, sizeof(entropy)); + return ENTROPY_DEBUG("arc4random_buf", entropy); +#else + /* Try high quality providers first .. */ +#ifdef _WIN32 + if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) { + return ENTROPY_DEBUG("RtlGenRandom", entropy); + } +#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) + if (writeRandomBytes_getrandom((void *)&entropy, sizeof(entropy))) { + return ENTROPY_DEBUG("getrandom", entropy); + } +#endif + /* .. and self-made low quality for backup: */ + + /* Process ID is 0 bits entropy if attacker has local access */ + entropy = gather_time_entropy() ^ getpid(); + + /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */ + if (sizeof(unsigned long) == 4) { + return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647); + } else { + return ENTROPY_DEBUG("fallback(8)", + entropy * (unsigned long)2305843009213693951); + } +#endif +} + +static unsigned long +get_hash_secret_salt(XML_Parser parser) { + if (parser->m_parentParser != NULL) + return get_hash_secret_salt(parser->m_parentParser); + return parser->m_hash_secret_salt; } @@ -705,3 +852,3 @@ startParsing(XML_Parser parser) if (hash_secret_salt == 0) - hash_secret_salt = generate_hash_secret_salt(); + hash_secret_salt = generate_hash_secret_salt(parser); if (ns) { @@ -928,2 +1075,6 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) OPEN_INTERNAL_ENTITY *openEntityList; + + if (parser == NULL) + return XML_FALSE; + if (parentParser) @@ -962,2 +1113,4 @@ XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { + if (parser == NULL) + return XML_STATUS_ERROR; /* Block after XML_Parse()/XML_ParseBuffer() has been called. @@ -985,42 +1138,34 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, DTD *newDtd = NULL; - DTD *oldDtd = _dtd; - XML_StartElementHandler oldStartElementHandler = startElementHandler; - XML_EndElementHandler oldEndElementHandler = endElementHandler; - XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; - XML_ProcessingInstructionHandler oldProcessingInstructionHandler - = processingInstructionHandler; - XML_CommentHandler oldCommentHandler = commentHandler; - XML_StartCdataSectionHandler oldStartCdataSectionHandler - = startCdataSectionHandler; - XML_EndCdataSectionHandler oldEndCdataSectionHandler - = endCdataSectionHandler; - XML_DefaultHandler oldDefaultHandler = defaultHandler; - XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler - = unparsedEntityDeclHandler; - XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; - XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler - = startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler - = endNamespaceDeclHandler; - XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; - XML_ExternalEntityRefHandler oldExternalEntityRefHandler - = externalEntityRefHandler; - XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; - XML_UnknownEncodingHandler oldUnknownEncodingHandler - = unknownEncodingHandler; - XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; - XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; - XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; - XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; - ELEMENT_TYPE * oldDeclElementType = declElementType; - - void *oldUserData = userData; - void *oldHandlerArg = handlerArg; - XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; - XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; + DTD *oldDtd; + XML_StartElementHandler oldStartElementHandler; + XML_EndElementHandler oldEndElementHandler; + XML_CharacterDataHandler oldCharacterDataHandler; + XML_ProcessingInstructionHandler oldProcessingInstructionHandler; + XML_CommentHandler oldCommentHandler; + XML_StartCdataSectionHandler oldStartCdataSectionHandler; + XML_EndCdataSectionHandler oldEndCdataSectionHandler; + XML_DefaultHandler oldDefaultHandler; + XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler; + XML_NotationDeclHandler oldNotationDeclHandler; + XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler; + XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler; + XML_NotStandaloneHandler oldNotStandaloneHandler; + XML_ExternalEntityRefHandler oldExternalEntityRefHandler; + XML_SkippedEntityHandler oldSkippedEntityHandler; + XML_UnknownEncodingHandler oldUnknownEncodingHandler; + XML_ElementDeclHandler oldElementDeclHandler; + XML_AttlistDeclHandler oldAttlistDeclHandler; + XML_EntityDeclHandler oldEntityDeclHandler; + XML_XmlDeclHandler oldXmlDeclHandler; + ELEMENT_TYPE * oldDeclElementType; + + void *oldUserData; + void *oldHandlerArg; + XML_Bool oldDefaultExpandInternalEntities; + XML_Parser oldExternalEntityRefHandlerArg; #ifdef XML_DTD - enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; - int oldInEntityValue = prologState.inEntityValue; + enum XML_ParamEntityParsing oldParamEntityParsing; + int oldInEntityValue; #endif - XML_Bool oldns_triplets = ns_triplets; + XML_Bool oldns_triplets; /* Note that the new parser shares the same hash secret as the old @@ -1030,3 +1175,47 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, */ - unsigned long oldhash_secret_salt = hash_secret_salt; + unsigned long oldhash_secret_salt; + + /* Validate the oldParser parameter before we pull everything out of it */ + if (oldParser == NULL) + return NULL; + + /* Stash the original parser contents on the stack */ + oldDtd = _dtd; + oldStartElementHandler = startElementHandler; + oldEndElementHandler = endElementHandler; + oldCharacterDataHandler = characterDataHandler; + oldProcessingInstructionHandler = processingInstructionHandler; + oldCommentHandler = commentHandler; + oldStartCdataSectionHandler = startCdataSectionHandler; + oldEndCdataSectionHandler = endCdataSectionHandler; + oldDefaultHandler = defaultHandler; + oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler; + oldNotationDeclHandler = notationDeclHandler; + oldStartNamespaceDeclHandler = startNamespaceDeclHandler; + oldEndNamespaceDeclHandler = endNamespaceDeclHandler; + oldNotStandaloneHandler = notStandaloneHandler; + oldExternalEntityRefHandler = externalEntityRefHandler; + oldSkippedEntityHandler = skippedEntityHandler; + oldUnknownEncodingHandler = unknownEncodingHandler; + oldElementDeclHandler = elementDeclHandler; + oldAttlistDeclHandler = attlistDeclHandler; + oldEntityDeclHandler = entityDeclHandler; + oldXmlDeclHandler = xmlDeclHandler; + oldDeclElementType = declElementType; + + oldUserData = userData; + oldHandlerArg = handlerArg; + oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; +#ifdef XML_DTD + oldParamEntityParsing = paramEntityParsing; + oldInEntityValue = prologState.inEntityValue; +#endif + oldns_triplets = ns_triplets; + /* Note that the new parser shares the same hash secret as the old + parser, so that dtdCopy and copyEntityTable can lookup values + from hash tables associated with either parser without us having + to worry which hash secrets each table has. + */ + oldhash_secret_salt = hash_secret_salt; @@ -1196,3 +1385,4 @@ XML_UseParserAsHandlerArg(XML_Parser parser) { - handlerArg = parser; + if (parser != NULL) + handlerArg = parser; } @@ -1202,2 +1392,4 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) { + if (parser == NULL) + return XML_ERROR_INVALID_ARGUMENT; #ifdef XML_DTD @@ -1216,2 +1408,4 @@ XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) { + if (parser == NULL) + return; /* block after XML_Parse()/XML_ParseBuffer() has been called */ @@ -1225,2 +1419,4 @@ XML_SetUserData(XML_Parser parser, void *p) { + if (parser == NULL) + return; if (handlerArg == userData) @@ -1234,2 +1430,4 @@ XML_SetBase(XML_Parser parser, const XML_Char *p) { + if (parser == NULL) + return XML_STATUS_ERROR; if (p) { @@ -1248,2 +1446,4 @@ XML_GetBase(XML_Parser parser) { + if (parser == NULL) + return NULL; return curBase; @@ -1254,2 +1454,4 @@ XML_GetSpecifiedAttributeCount(XML_Parser parser) { + if (parser == NULL) + return -1; return nSpecifiedAtts; @@ -1260,2 +1462,4 @@ XML_GetIdAttributeIndex(XML_Parser parser) { + if (parser == NULL) + return -1; return idAttIndex; @@ -1267,2 +1471,4 @@ XML_GetAttributeInfo(XML_Parser parser) { + if (parser == NULL) + return NULL; return attInfo; @@ -1276,2 +1482,4 @@ XML_SetElementHandler(XML_Parser parser, { + if (parser == NULL) + return; startElementHandler = start; @@ -1283,3 +1491,4 @@ XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) { - startElementHandler = start; + if (parser != NULL) + startElementHandler = start; } @@ -1289,3 +1498,4 @@ XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) { - endElementHandler = end; + if (parser != NULL) + endElementHandler = end; } @@ -1296,3 +1506,4 @@ XML_SetCharacterDataHandler(XML_Parser parser, { - characterDataHandler = handler; + if (parser != NULL) + characterDataHandler = handler; } @@ -1303,3 +1514,4 @@ XML_SetProcessingInstructionHandler(XML_Parser parser, { - processingInstructionHandler = handler; + if (parser != NULL) + processingInstructionHandler = handler; } @@ -1310,3 +1522,4 @@ XML_SetCommentHandler(XML_Parser parser, { - commentHandler = handler; + if (parser != NULL) + commentHandler = handler; } @@ -1318,2 +1531,4 @@ XML_SetCdataSectionHandler(XML_Parser parser, { + if (parser == NULL) + return; startCdataSectionHandler = start; @@ -1325,3 +1540,4 @@ XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start) { - startCdataSectionHandler = start; + if (parser != NULL) + startCdataSectionHandler = start; } @@ -1331,3 +1547,4 @@ XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end) { - endCdataSectionHandler = end; + if (parser != NULL) + endCdataSectionHandler = end; } @@ -1338,2 +1555,4 @@ XML_SetDefaultHandler(XML_Parser parser, { + if (parser == NULL) + return; defaultHandler = handler; @@ -1346,2 +1565,4 @@ XML_SetDefaultHandlerExpand(XML_Parser parser, { + if (parser == NULL) + return; defaultHandler = handler; @@ -1355,2 +1576,4 @@ XML_SetDoctypeDeclHandler(XML_Parser parser, { + if (parser == NULL) + return; startDoctypeDeclHandler = start; @@ -1362,3 +1585,4 @@ XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start) { - startDoctypeDeclHandler = start; + if (parser != NULL) + startDoctypeDeclHandler = start; } @@ -1368,3 +1592,4 @@ XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) { - endDoctypeDeclHandler = end; + if (parser != NULL) + endDoctypeDeclHandler = end; } @@ -1375,3 +1600,4 @@ XML_SetUnparsedEntityDeclHandler(XML_Parser parser, { - unparsedEntityDeclHandler = handler; + if (parser != NULL) + unparsedEntityDeclHandler = handler; } @@ -1382,3 +1608,4 @@ XML_SetNotationDeclHandler(XML_Parser parser, { - notationDeclHandler = handler; + if (parser != NULL) + notationDeclHandler = handler; } @@ -1390,2 +1617,4 @@ XML_SetNamespaceDeclHandler(XML_Parser parser, { + if (parser == NULL) + return; startNamespaceDeclHandler = start; @@ -1397,3 +1626,4 @@ XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start) { - startNamespaceDeclHandler = start; + if (parser != NULL) + startNamespaceDeclHandler = start; } @@ -1403,3 +1633,4 @@ XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end) { - endNamespaceDeclHandler = end; + if (parser != NULL) + endNamespaceDeclHandler = end; } @@ -1410,3 +1641,4 @@ XML_SetNotStandaloneHandler(XML_Parser parser, { - notStandaloneHandler = handler; + if (parser != NULL) + notStandaloneHandler = handler; } @@ -1417,3 +1649,4 @@ XML_SetExternalEntityRefHandler(XML_Parser parser, { - externalEntityRefHandler = handler; + if (parser != NULL) + externalEntityRefHandler = handler; } @@ -1423,2 +1656,4 @@ XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) { + if (parser == NULL) + return; if (arg) @@ -1433,3 +1668,4 @@ XML_SetSkippedEntityHandler(XML_Parser parser, { - skippedEntityHandler = handler; + if (parser != NULL) + skippedEntityHandler = handler; } @@ -1441,2 +1677,4 @@ XML_SetUnknownEncodingHandler(XML_Parser parser, { + if (parser == NULL) + return; unknownEncodingHandler = handler; @@ -1449,3 +1687,4 @@ XML_SetElementDeclHandler(XML_Parser parser, { - elementDeclHandler = eldecl; + if (parser != NULL) + elementDeclHandler = eldecl; } @@ -1456,3 +1695,4 @@ XML_SetAttlistDeclHandler(XML_Parser parser, { - attlistDeclHandler = attdecl; + if (parser != NULL) + attlistDeclHandler = attdecl; } @@ -1463,3 +1703,4 @@ XML_SetEntityDeclHandler(XML_Parser parser, { - entityDeclHandler = handler; + if (parser != NULL) + entityDeclHandler = handler; } @@ -1469,3 +1710,4 @@ XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) { - xmlDeclHandler = handler; + if (parser != NULL) + xmlDeclHandler = handler; } @@ -1476,2 +1718,4 @@ XML_SetParamEntityParsing(XML_Parser parser, { + if (parser == NULL) + return 0; /* block after XML_Parse()/XML_ParseBuffer() has been called */ @@ -1491,2 +1735,6 @@ XML_SetHashSalt(XML_Parser parser, { + if (parser == NULL) + return 0; + if (parser->m_parentParser) + return XML_SetHashSalt(parser->m_parentParser, hash_salt); /* block after XML_Parse()/XML_ParseBuffer() has been called */ @@ -1501,2 +1749,6 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { + if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) { + errorCode = XML_ERROR_INVALID_ARGUMENT; + return XML_STATUS_ERROR; + } switch (ps_parsing) { @@ -1552,3 +1804,10 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) int nLeftOver; - enum XML_Error result; + enum XML_Status result; + /* Detect overflow (a+b > MAX <==> b > MAX-a) */ + if (len > ((XML_Size)-1) / 2 - parseEndByteIndex) { + errorCode = XML_ERROR_NO_MEMORY; + eventPtr = eventEndPtr = NULL; + processor = errorProcessor; + return XML_STATUS_ERROR; + } parseEndByteIndex += len; @@ -1585,7 +1844,10 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) if (buffer == NULL || nLeftOver > bufferLim - buffer) { - /* FIXME avoid integer overflow */ - char *temp; - temp = (buffer == NULL - ? (char *)MALLOC(len * 2) - : (char *)REALLOC(buffer, len * 2)); + /* avoid _signed_ integer overflow */ + char *temp = NULL; + const int bytesToAllocate = (int)((unsigned)len * 2U); + if (bytesToAllocate > 0) { + temp = (buffer == NULL + ? (char *)MALLOC(bytesToAllocate) + : (char *)REALLOC(buffer, bytesToAllocate)); + } if (temp == NULL) { @@ -1597,3 +1859,3 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) buffer = temp; - bufferLim = buffer + len * 2; + bufferLim = buffer + bytesToAllocate; } @@ -1627,2 +1889,4 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) + if (parser == NULL) + return XML_STATUS_ERROR; switch (ps_parsing) { @@ -1680,2 +1944,8 @@ XML_GetBuffer(XML_Parser parser, int len) { + if (parser == NULL) + return NULL; + if (len < 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } switch (ps_parsing) { @@ -1691,7 +1961,13 @@ XML_GetBuffer(XML_Parser parser, int len) if (len > bufferLim - bufferEnd) { - /* FIXME avoid integer overflow */ - int neededSize = len + (int)(bufferEnd - bufferPtr); #ifdef XML_CONTEXT_BYTES - int keep = (int)(bufferPtr - buffer); - + int keep; +#endif /* defined XML_CONTEXT_BYTES */ + /* Do not invoke signed arithmetic overflow: */ + int neededSize = (int) ((unsigned)len + (unsigned)(bufferEnd - bufferPtr)); + if (neededSize < 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } +#ifdef XML_CONTEXT_BYTES + keep = (int)(bufferPtr - buffer); if (keep > XML_CONTEXT_BYTES) @@ -1720,4 +1996,9 @@ XML_GetBuffer(XML_Parser parser, int len) do { - bufferSize *= 2; - } while (bufferSize < neededSize); + /* Do not invoke signed arithmetic overflow: */ + bufferSize = (int) (2U * (unsigned) bufferSize); + } while (bufferSize < neededSize && bufferSize > 0); + if (bufferSize <= 0) { + errorCode = XML_ERROR_NO_MEMORY; + return NULL; + } newBuf = (char *)MALLOC(bufferSize); @@ -1761,2 +2042,4 @@ XML_StopParser(XML_Parser parser, XML_Bool resumable) { + if (parser == NULL) + return XML_STATUS_ERROR; switch (ps_parsing) { @@ -1793,2 +2076,4 @@ XML_ResumeParser(XML_Parser parser) + if (parser == NULL) + return XML_STATUS_ERROR; if (ps_parsing != XML_SUSPENDED) { @@ -1829,2 +2114,4 @@ XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) { + if (parser == NULL) + return; assert(status != NULL); @@ -1836,2 +2123,4 @@ XML_GetErrorCode(XML_Parser parser) { + if (parser == NULL) + return XML_ERROR_INVALID_ARGUMENT; return errorCode; @@ -1842,4 +2131,6 @@ XML_GetCurrentByteIndex(XML_Parser parser) { + if (parser == NULL) + return -1; if (eventPtr) - return parseEndByteIndex - (parseEndPtr - eventPtr); + return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr)); return -1; @@ -1850,2 +2141,4 @@ XML_GetCurrentByteCount(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventEndPtr && eventPtr) @@ -1859,7 +2152,15 @@ XML_GetInputContext(XML_Parser parser, int *offset, int *size) #ifdef XML_CONTEXT_BYTES + if (parser == NULL) + return NULL; if (eventPtr && buffer) { - *offset = (int)(eventPtr - buffer); - *size = (int)(bufferEnd - buffer); + if (offset != NULL) + *offset = (int)(eventPtr - buffer); + if (size != NULL) + *size = (int)(bufferEnd - buffer); return buffer; } +#else + (void)parser; + (void)offset; + (void)size; #endif /* defined XML_CONTEXT_BYTES */ @@ -1871,2 +2172,4 @@ XML_GetCurrentLineNumber(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventPtr && eventPtr >= positionPtr) { @@ -1881,2 +2184,4 @@ XML_GetCurrentColumnNumber(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventPtr && eventPtr >= positionPtr) { @@ -1891,3 +2196,4 @@ XML_FreeContentModel(XML_Parser parser, XML_Content *model) { - FREE(model); + if (parser != NULL) + FREE(model); } @@ -1897,2 +2203,4 @@ XML_MemMalloc(XML_Parser parser, size_t size) { + if (parser == NULL) + return NULL; return MALLOC(size); @@ -1903,2 +2211,4 @@ XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) { + if (parser == NULL) + return NULL; return REALLOC(ptr, size); @@ -1909,3 +2219,4 @@ XML_MemFree(XML_Parser parser, void *ptr) { - FREE(ptr); + if (parser != NULL) + FREE(ptr); } @@ -1915,2 +2226,4 @@ XML_DefaultCurrent(XML_Parser parser) { + if (parser == NULL) + return; if (defaultHandler) { @@ -2417,3 +2730,3 @@ doContent(XML_Parser parser, int convLen; - XmlConvert(enc, + const enum XML_Convert_Result convert_res = XmlConvert(enc, &fromPtr, rawNameEnd, @@ -2421,3 +2734,3 @@ doContent(XML_Parser parser, convLen = (int)(toPtr - (XML_Char *)tag->buf); - if (fromPtr == rawNameEnd) { + if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) { tag->name.strLen = convLen; @@ -2464,4 +2777,6 @@ doContent(XML_Parser parser, result = storeAtts(parser, enc, s, &name, &bindings); - if (result) + if (result != XML_ERROR_NONE) { + freeBindings(parser, bindings); return result; + } poolFinish(&tempPool); @@ -2480,11 +2795,3 @@ doContent(XML_Parser parser, poolClear(&tempPool); - while (bindings) { - BINDING *b = bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - bindings = bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } + freeBindings(parser, bindings); } @@ -2642,3 +2949,3 @@ doContent(XML_Parser parser, ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = s; @@ -2646,3 +2953,3 @@ doContent(XML_Parser parser, (int)(dataPtr - (ICHAR *)dataBuf)); - if (s == next) + if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) break; @@ -2686,2 +2993,25 @@ doContent(XML_Parser parser, +/* This function does not call free() on the allocated memory, merely + * moving it to the parser's freeBindingList where it can be freed or + * reused as appropriate. + */ +static void +freeBindings(XML_Parser parser, BINDING *bindings) +{ + while (bindings) { + BINDING *b = bindings; + + /* startNamespaceDeclHandler will have been called for this + * binding in addBindings(), so call the end handler now. + */ + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } +} + /* Precondition: all arguments must be non-NULL; @@ -2910,12 +3240,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const BINDING *b; - unsigned long uriHash = hash_secret_salt; + unsigned long uriHash; + struct siphash sip_state; + struct sipkey sip_key; + + copy_salt_to_sipkey(parser, &sip_key); + sip24_init(&sip_state, &sip_key); + ((XML_Char *)s)[-1] = 0; /* clear flag */ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0); + if (!id || !id->prefix) + return XML_ERROR_NO_MEMORY; b = id->prefix->binding; - if (!b) { - //return XML_ERROR_UNBOUND_PREFIX; - continue; - } + if (!b) + return XML_ERROR_UNBOUND_PREFIX; - /* as we expand the name we also calculate its hash value */ for (j = 0; j < b->uriLen; j++) { @@ -2924,13 +3259,18 @@ storeAtts(XML_Parser parser, const ENCODING *enc, return XML_ERROR_NO_MEMORY; - uriHash = CHAR_HASH(uriHash, c); } + + sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char)); + while (*s++ != XML_T(ASCII_COLON)) ; + + sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char)); + do { /* copies null terminator */ - const XML_Char c = *s; if (!poolAppendChar(&tempPool, *s)) return XML_ERROR_NO_MEMORY; - uriHash = CHAR_HASH(uriHash, c); } while (*s++); + uriHash = (unsigned long)sip24_final(&sip_state); + { /* Check hash table for duplicate of expanded name (uriName). @@ -2995,3 +3335,3 @@ storeAtts(XML_Parser parser, const ENCODING *enc, /* expand the element type name */ - if (elementType->prefix && elementType->prefix->binding) { + if (elementType->prefix) { binding = elementType->prefix->binding; @@ -3091,6 +3431,6 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, /* Not allowed to bind xmlns */ - /*if (prefix->name[3] == XML_T(ASCII_n) + if (prefix->name[3] == XML_T(ASCII_n) && prefix->name[4] == XML_T(ASCII_s) && prefix->name[5] == XML_T('\0')) - return XML_ERROR_RESERVED_PREFIX_XMLNS;*/ + return XML_ERROR_RESERVED_PREFIX_XMLNS; @@ -3111,8 +3451,8 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, - /*if (mustBeXML != isXML) + if (mustBeXML != isXML) return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML - : XML_ERROR_RESERVED_NAMESPACE_URI;*/ + : XML_ERROR_RESERVED_NAMESPACE_URI; - /*if (isXMLNS) - return XML_ERROR_RESERVED_NAMESPACE_URI;*/ + if (isXMLNS) + return XML_ERROR_RESERVED_NAMESPACE_URI; @@ -3252,3 +3592,3 @@ doCdataSection(XML_Parser parser, ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = next; @@ -3256,3 +3596,3 @@ doCdataSection(XML_Parser parser, (int)(dataPtr - (ICHAR *)dataBuf)); - if (s == next) + if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) break; @@ -3648,2 +3988,10 @@ entityValueInitProcessor(XML_Parser parser, } + /* If we get this token, we have the start of what might be a + normal tag, but not a declaration (i.e. it doesn't begin with + "<!"). In a DTD context, that isn't legal. + */ + else if (tok == XML_TOK_INSTANCE_START) { + *nextPtr = next; + return XML_ERROR_SYNTAX; + } start = next; @@ -4824,2 +5172,4 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, textEnd = (char *)(entity->textPtr + entity->textLen); + /* Set a safe default value in case 'next' does not get set */ + next = textStart; @@ -4869,2 +5219,4 @@ internalEntityProcessor(XML_Parser parser, textEnd = (char *)(entity->textPtr + entity->textLen); + /* Set a safe default value in case 'next' does not get set */ + next = textStart; @@ -4915,5 +5267,5 @@ static enum XML_Error PTRCALL errorProcessor(XML_Parser parser, - const char *s, - const char *end, - const char **nextPtr) + const char *UNUSED_P(s), + const char *UNUSED_P(end), + const char **UNUSED_P(nextPtr)) { @@ -5333,2 +5685,3 @@ reportDefault(XML_Parser parser, const ENCODING *enc, if (MUST_CONVERT(enc, s)) { + enum XML_Convert_Result convert_res; const char **eventPP; @@ -5345,3 +5698,3 @@ reportDefault(XML_Parser parser, const ENCODING *enc, ICHAR *dataPtr = (ICHAR *)dataBuf; - XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); *eventEndPP = s; @@ -5349,3 +5702,3 @@ reportDefault(XML_Parser parser, const ENCODING *enc, *eventPP = s; - } while (s != end); + } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE)); } @@ -5479,2 +5832,4 @@ getAttributeId(XML_Parser parser, const ENCODING *enc, sizeof(PREFIX)); + if (!id->prefix) + return NULL; if (id->prefix->name == poolStart(&dtd->pool)) @@ -5826,3 +6181,2 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_H if (!newE->defaultAtts) { - ms->free_fcn(newE); return 0; @@ -5961,2 +6315,17 @@ keyeq(KEY s1, KEY s2) +static size_t +keylen(KEY s) +{ + size_t len = 0; + for (; *s; s++, len++); + return len; +} + +static void +copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key) +{ + key->k[0] = 0; + key->k[1] = get_hash_secret_salt(parser); +} + static unsigned long FASTCALL @@ -5964,6 +6333,10 @@ hash(XML_Parser parser, KEY s) { - unsigned long h = hash_secret_salt; - while (*s) - h = CHAR_HASH(h, *s++); - return h; + struct siphash state; + struct sipkey key; + (void)sip_tobin; + (void)sip24_valid; + copy_salt_to_sipkey(parser, &key); + sip24_init(&state, &key); + sip24_update(&state, s, keylen(s) * sizeof(XML_Char)); + return (unsigned long)sip24_final(&state); } @@ -6152,4 +6525,4 @@ poolAppend(STRING_POOL *pool, const ENCODING *enc, for (;;) { - XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); - if (ptr == end) + const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); + if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) break; @@ -6210,2 +6583,31 @@ poolStoreString(STRING_POOL *pool, const ENCODING *enc, +static size_t +poolBytesToAllocateFor(int blockSize) +{ + /* Unprotected math would be: + ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char); + ** + ** Detect overflow, avoiding _signed_ overflow undefined behavior + ** For a + b * c we check b * c in isolation first, so that addition of a + ** on top has no chance of making us accept a small non-negative number + */ + const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */ + + if (blockSize <= 0) + return 0; + + if (blockSize > (int)(INT_MAX / stretch)) + return 0; + + { + const int stretchedBlockSize = blockSize * (int)stretch; + const int bytesToAllocate = (int)( + offsetof(BLOCK, s) + (unsigned)stretchedBlockSize); + if (bytesToAllocate < 0) + return 0; + + return (size_t)bytesToAllocate; + } +} + static XML_Bool FASTCALL @@ -6237,7 +6639,15 @@ poolGrow(STRING_POOL *pool) if (pool->blocks && pool->start == pool->blocks->s) { - int blockSize = (int)(pool->end - pool->start)*2; - BLOCK *temp = (BLOCK *) - pool->mem->realloc_fcn(pool->blocks, - (offsetof(BLOCK, s) - + blockSize * sizeof(XML_Char))); + BLOCK *temp; + int blockSize = (int)((unsigned)(pool->end - pool->start)*2U); + size_t bytesToAllocate; + + if (blockSize < 0) + return XML_FALSE; + + bytesToAllocate = poolBytesToAllocateFor(blockSize); + if (bytesToAllocate == 0) + return XML_FALSE; + + temp = (BLOCK *) + pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate); if (temp == NULL) @@ -6253,8 +6663,22 @@ poolGrow(STRING_POOL *pool) int blockSize = (int)(pool->end - pool->start); + size_t bytesToAllocate; + + if (blockSize < 0) + return XML_FALSE; + if (blockSize < INIT_BLOCK_SIZE) blockSize = INIT_BLOCK_SIZE; - else + else { + /* Detect overflow, avoiding _signed_ overflow undefined behavior */ + if ((int)((unsigned)blockSize * 2U) < 0) { + return XML_FALSE; + } blockSize *= 2; - tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) - + blockSize * sizeof(XML_Char)); + } + + bytesToAllocate = poolBytesToAllocateFor(blockSize); + if (bytesToAllocate == 0) + return XML_FALSE; + + tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate); if (!tem) |