You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by ar...@apache.org on 2022/03/17 18:00:36 UTC
[openoffice] 02/02: Produce expat-2.2.13, derived from 2.4.7
This is an automated email from the ASF dual-hosted git repository.
ardovm pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/openoffice.git
commit 84b800346361a798f2dacc3e03dc6b4a6358f3cf
Author: Arrigo Marchiori <ar...@yahoo.it>
AuthorDate: Wed Mar 9 21:11:35 2022 +0100
Produce expat-2.2.13, derived from 2.4.7
---
main/expat/expat-2.2.10.patch | 888 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 786 insertions(+), 102 deletions(-)
diff --git a/main/expat/expat-2.2.10.patch b/main/expat/expat-2.2.10.patch
index b6413d6..0de7936 100644
--- a/main/expat/expat-2.2.10.patch
+++ b/main/expat/expat-2.2.10.patch
@@ -360,7 +360,7 @@ diff -ru misc/expat-2.2.10/doc/xmlwf.xml misc/build/expat-2.2.10/doc/xmlwf.xml
</para>
diff -ru misc/expat-2.2.10/lib/expat.h misc/build/expat-2.2.10/lib/expat.h
--- misc/expat-2.2.10/lib/expat.h 2020-10-03 17:14:57.000000000 +0200
-+++ misc/build/expat-2.2.10/lib/expat.h 2022-03-05 12:25:27.583396678 +0100
++++ misc/build/expat-2.2.10/lib/expat.h 2022-03-09 20:25:36.712575539 +0100
@@ -115,7 +115,10 @@
XML_ERROR_RESERVED_PREFIX_XMLNS,
XML_ERROR_RESERVED_NAMESPACE_URI,
@@ -408,7 +408,7 @@ diff -ru misc/expat-2.2.10/lib/expat.h misc/build/expat-2.2.10/lib/expat.h
#define XML_MAJOR_VERSION 2
#define XML_MINOR_VERSION 2
-#define XML_MICRO_VERSION 10
-+#define XML_MICRO_VERSION 12
++#define XML_MICRO_VERSION 13
#ifdef __cplusplus
}
@@ -520,7 +520,7 @@ diff -ru misc/expat-2.2.10/lib/Makefile.in misc/build/expat-2.2.10/lib/Makefile.
srcdir = @srcdir@
diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
--- misc/expat-2.2.10/lib/xmlparse.c 2020-10-03 17:14:57.000000000 +0200
-+++ misc/build/expat-2.2.10/lib/xmlparse.c 2022-03-05 12:25:27.583396678 +0100
++++ misc/build/expat-2.2.10/lib/xmlparse.c 2022-03-09 20:25:36.712575539 +0100
@@ -47,6 +47,7 @@
#include <limits.h> /* UINT_MAX */
#include <stdio.h> /* fprintf */
@@ -540,6 +540,15 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
#elif defined(HAVE_EXPAT_CONFIG_H)
# include <expat_config.h>
#endif /* ndef _WIN32 */
+@@ -116,7 +121,7 @@
+ * BSD / macOS (including <10.7) (arc4random): HAVE_ARC4RANDOM, \
+ * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
+ * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
+- * Linux (including <3.17) / BSD / macOS (including <10.7) (/dev/urandom): XML_DEV_URANDOM, \
++ * Linux (including <3.17) / BSD / macOS (including <10.7) / Solaris >=8 (/dev/urandom): XML_DEV_URANDOM, \
+ * Windows >=Vista (rand_s): _WIN32. \
+ \
+ If insist on not using any of these, bypass this error by defining \
@@ -382,6 +387,31 @@
XML_Bool betweenDecl; /* WFC: PE Between Declarations */
} OPEN_INTERNAL_ENTITY;
@@ -672,7 +681,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
};
#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
-@@ -640,6 +708,7 @@
+@@ -640,9 +708,11 @@
XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
XML_Char tmp[2];
*tmp = nsSep;
@@ -680,7 +689,11 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
return XML_ParserCreate_MM(encodingName, NULL, tmp);
}
-@@ -809,9 +878,8 @@
++// "xml=http://www.w3.org/XML/1998/namespace"
+ static const XML_Char implicitContext[]
+ = {ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h,
+ ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH,
+@@ -809,9 +879,8 @@
static unsigned long
ENTROPY_DEBUG(const char *label, unsigned long entropy) {
@@ -692,7 +705,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
(int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
}
return entropy;
-@@ -855,7 +923,7 @@
+@@ -855,7 +924,7 @@
return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
} else {
return ENTROPY_DEBUG("fallback(8)",
@@ -701,7 +714,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
}
#endif
}
-@@ -1073,6 +1141,18 @@
+@@ -1073,6 +1142,18 @@
parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
#endif
parser->m_hash_secret_salt = 0;
@@ -720,7 +733,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
}
/* moves list of bindings to m_freeBindingList */
-@@ -1255,6 +1335,7 @@
+@@ -1255,6 +1336,7 @@
if (parser->m_ns) {
XML_Char tmp[2];
*tmp = parser->m_namespaceSeparator;
@@ -728,7 +741,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
} else {
parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
-@@ -1893,6 +1974,12 @@
+@@ -1893,6 +1975,12 @@
parser->m_errorCode = XML_ERROR_FINISHED;
return XML_STATUS_ERROR;
case XML_INITIALIZED:
@@ -741,7 +754,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (parser->m_parentParser == NULL && ! startParsing(parser)) {
parser->m_errorCode = XML_ERROR_NO_MEMORY;
return XML_STATUS_ERROR;
-@@ -1971,6 +2058,11 @@
+@@ -1971,6 +2059,11 @@
keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
if (keep > XML_CONTEXT_BYTES)
keep = XML_CONTEXT_BYTES;
@@ -753,7 +766,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
neededSize += keep;
#endif /* defined XML_CONTEXT_BYTES */
if (neededSize
-@@ -2337,6 +2429,13 @@
+@@ -2337,6 +2430,13 @@
/* Added in 2.2.5. */
case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
return XML_L("invalid argument");
@@ -767,7 +780,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
}
return NULL;
}
-@@ -2373,41 +2472,75 @@
+@@ -2373,41 +2473,75 @@
const XML_Feature *XMLCALL
XML_GetFeatureList(void) {
@@ -858,7 +871,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
/* Initially tag->rawName always points into the parse buffer;
for those TAG instances opened while the current parse buffer was
processed, and not yet closed, we need to store tag->rawName in a more
-@@ -2419,6 +2552,7 @@
+@@ -2419,6 +2553,7 @@
while (tag) {
int bufSize;
int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
@@ -866,7 +879,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
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
-@@ -2430,7 +2564,11 @@
+@@ -2430,7 +2565,11 @@
/* For re-use purposes we need to ensure that the
size of tag->buf is a multiple of sizeof(XML_Char).
*/
@@ -879,7 +892,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (bufSize > tag->bufEnd - tag->buf) {
char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
if (temp == NULL)
-@@ -2460,9 +2598,9 @@
+@@ -2460,9 +2599,9 @@
static enum XML_Error PTRCALL
contentProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
@@ -892,7 +905,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result == XML_ERROR_NONE) {
if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
-@@ -2487,6 +2625,14 @@
+@@ -2487,6 +2626,14 @@
int tok = XmlContentTok(parser->m_encoding, start, end, &next);
switch (tok) {
case XML_TOK_BOM:
@@ -907,7 +920,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
/* If we are at the end of the buffer, this would cause the next stage,
i.e. externalEntityInitProcessor3, to pass control directly to
doContent (by detecting XML_TOK_NONE) without processing any xml text
-@@ -2524,6 +2670,10 @@
+@@ -2524,6 +2671,10 @@
const char *next = start; /* XmlContentTok doesn't always set the last arg */
parser->m_eventPtr = start;
tok = XmlContentTok(parser->m_encoding, start, end, &next);
@@ -918,7 +931,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
parser->m_eventEndPtr = next;
switch (tok) {
-@@ -2565,7 +2715,8 @@
+@@ -2565,7 +2716,8 @@
const char *end, const char **endPtr) {
enum XML_Error result
= doContent(parser, 1, parser->m_encoding, start, end, endPtr,
@@ -928,7 +941,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result == XML_ERROR_NONE) {
if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
-@@ -2576,7 +2727,7 @@
+@@ -2576,7 +2728,7 @@
static enum XML_Error
doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
const char *s, const char *end, const char **nextPtr,
@@ -937,7 +950,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
/* save one level of indirection */
DTD *const dtd = parser->m_dtd;
-@@ -2594,6 +2745,17 @@
+@@ -2594,6 +2746,17 @@
for (;;) {
const char *next = s; /* XmlContentTok doesn't always set the last arg */
int tok = XmlContentTok(enc, s, end, &next);
@@ -955,7 +968,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
*eventEndPP = next;
switch (tok) {
case XML_TOK_TRAILING_CR:
-@@ -2649,6 +2811,14 @@
+@@ -2649,6 +2812,14 @@
XML_Char ch = (XML_Char)XmlPredefinedEntityName(
enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
if (ch) {
@@ -970,7 +983,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (parser->m_characterDataHandler)
parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
else if (parser->m_defaultHandler)
-@@ -2767,7 +2937,7 @@
+@@ -2767,7 +2938,7 @@
}
tag->name.str = (XML_Char *)tag->buf;
*toPtr = XML_T('\0');
@@ -979,7 +992,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result)
return result;
if (parser->m_startElementHandler)
-@@ -2791,7 +2961,8 @@
+@@ -2791,7 +2962,8 @@
if (! name.str)
return XML_ERROR_NO_MEMORY;
poolFinish(&parser->m_tempPool);
@@ -989,7 +1002,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result != XML_ERROR_NONE) {
freeBindings(parser, bindings);
return result;
-@@ -2926,7 +3097,7 @@
+@@ -2926,7 +3098,7 @@
/* END disabled code */
else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, next);
@@ -998,7 +1011,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result != XML_ERROR_NONE)
return result;
else if (! next) {
-@@ -3055,7 +3226,8 @@
+@@ -3055,7 +3227,8 @@
*/
static enum XML_Error
storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
@@ -1008,7 +1021,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
ELEMENT_TYPE *elementType;
int nDefaultAtts;
-@@ -3087,13 +3259,38 @@
+@@ -3087,13 +3260,38 @@
/* get the attributes from the tokenizer */
n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
@@ -1047,7 +1060,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
parser->m_attsSize * sizeof(ATTRIBUTE));
if (temp == NULL) {
-@@ -3102,6 +3299,17 @@
+@@ -3102,6 +3300,17 @@
}
parser->m_atts = temp;
#ifdef XML_ATTR_INFO
@@ -1065,7 +1078,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
parser->m_attsSize * sizeof(XML_AttrInfo));
if (temp2 == NULL) {
-@@ -3165,7 +3373,7 @@
+@@ -3165,7 +3374,7 @@
/* normalize the attribute value */
result = storeAttributeValue(
parser, enc, isCdata, parser->m_atts[i].valuePtr,
@@ -1074,7 +1087,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result)
return result;
appAtts[attIndex] = poolStart(&parser->m_tempPool);
-@@ -3240,8 +3448,16 @@
+@@ -3240,8 +3449,16 @@
if (nPrefixes) {
int j; /* hash table index */
unsigned long version = parser->m_nsAttsVersion;
@@ -1093,7 +1106,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
/* size of hash table must be at least 2 * (# of prefixed attributes) */
if ((nPrefixes << 1)
>> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
-@@ -3251,7 +3467,28 @@
+@@ -3251,7 +3468,28 @@
;
if (parser->m_nsAttsPower < 3)
parser->m_nsAttsPower = 3;
@@ -1123,7 +1136,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
nsAttsSize * sizeof(NS_ATT));
if (! temp) {
-@@ -3409,9 +3646,31 @@
+@@ -3409,9 +3647,31 @@
tagNamePtr->prefixLen = prefixLen;
for (i = 0; localPart[i++];)
; /* i includes null terminator */
@@ -1155,25 +1168,170 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
if (! uri)
return XML_ERROR_NO_MEMORY;
-@@ -3491,6 +3750,17 @@
+@@ -3436,12 +3696,124 @@
+ return XML_ERROR_NONE;
+ }
+
++static XML_Bool
++is_rfc3986_uri_char(XML_Char candidate) {
++ // For the RFC 3986 ANBF grammar see
++ // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A
++
++ switch (candidate) {
++ // From rule "ALPHA" (uppercase half)
++ case 'A':
++ case 'B':
++ case 'C':
++ case 'D':
++ case 'E':
++ case 'F':
++ case 'G':
++ case 'H':
++ case 'I':
++ case 'J':
++ case 'K':
++ case 'L':
++ case 'M':
++ case 'N':
++ case 'O':
++ case 'P':
++ case 'Q':
++ case 'R':
++ case 'S':
++ case 'T':
++ case 'U':
++ case 'V':
++ case 'W':
++ case 'X':
++ case 'Y':
++ case 'Z':
++
++ // From rule "ALPHA" (lowercase half)
++ case 'a':
++ case 'b':
++ case 'c':
++ case 'd':
++ case 'e':
++ case 'f':
++ case 'g':
++ case 'h':
++ case 'i':
++ case 'j':
++ case 'k':
++ case 'l':
++ case 'm':
++ case 'n':
++ case 'o':
++ case 'p':
++ case 'q':
++ case 'r':
++ case 's':
++ case 't':
++ case 'u':
++ case 'v':
++ case 'w':
++ case 'x':
++ case 'y':
++ case 'z':
++
++ // From rule "DIGIT"
++ case '0':
++ case '1':
++ case '2':
++ case '3':
++ case '4':
++ case '5':
++ case '6':
++ case '7':
++ case '8':
++ case '9':
++
++ // From rule "pct-encoded"
++ case '%':
++
++ // From rule "unreserved"
++ case '-':
++ case '.':
++ case '_':
++ case '~':
++
++ // From rule "gen-delims"
++ case ':':
++ case '/':
++ case '?':
++ case '#':
++ case '[':
++ case ']':
++ case '@':
++
++ // From rule "sub-delims"
++ case '!':
++ case '$':
++ case '&':
++ case '\'':
++ case '(':
++ case ')':
++ case '*':
++ case '+':
++ case ',':
++ case ';':
++ case '=':
++ return XML_TRUE;
++
++ default:
++ return XML_FALSE;
++ }
++}
++
+ /* addBinding() overwrites the value of prefix->binding without checking.
+ Therefore one must keep track of the old value outside of addBinding().
+ */
+ static enum XML_Error
+ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
+ const XML_Char *uri, BINDING **bindingsPtr) {
++ // "http://www.w3.org/XML/1998/namespace"
+ static const XML_Char xmlNamespace[]
+ = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON,
+ ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
+@@ -3452,6 +3824,7 @@
+ ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
+ ASCII_e, '\0'};
+ static const int xmlLen = (int)sizeof(xmlNamespace) / sizeof(XML_Char) - 1;
++ // "http://www.w3.org/2000/xmlns/"
+ static const XML_Char xmlnsNamespace[]
+ = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH,
+ ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w,
+@@ -3491,6 +3864,29 @@
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)) {
++ // NOTE: While Expat does not validate namespace URIs against RFC 3986
++ // today (and is not REQUIRED to do so with regard to the XML 1.0
++ // namespaces specification) we have to at least make sure, that
++ // the application on top of Expat (that is likely splitting expanded
++ // element names ("qualified names") of form
++ // "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces
++ // in its element handler code) cannot be confused by an attacker
++ // putting additional namespace separator characters into namespace
++ // declarations. That would be ambiguous and not to be expected.
++ //
++ // While the HTML API docs of function XML_ParserCreateNS have been
++ // advising against use of a namespace separator character that can
++ // appear in a URI for >20 years now, some widespread applications
++ // are using URI characters (':' (colon) in particular) for a
++ // namespace separator, in practice. To keep these applications
++ // functional, we only reject namespaces URIs containing the
++ // application-chosen namespace separator if the chosen separator
++ // is a non-URI character with regard to RFC 3986.
++ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)
++ && ! is_rfc3986_uri_char(uri[len])) {
+ return XML_ERROR_SYNTAX;
+ }
}
isXML = isXML && len == xmlLen;
isXMLNS = isXMLNS && len == xmlnsLen;
-@@ -3507,7 +3777,24 @@
+@@ -3507,7 +3903,24 @@
if (parser->m_freeBindingList) {
b = parser->m_freeBindingList;
if (len > b->uriAlloc) {
@@ -1199,7 +1357,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
if (temp == NULL)
return XML_ERROR_NO_MEMORY;
-@@ -3519,6 +3806,21 @@
+@@ -3519,6 +3932,21 @@
b = (BINDING *)MALLOC(parser, sizeof(BINDING));
if (! b)
return XML_ERROR_NO_MEMORY;
@@ -1221,7 +1379,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
b->uri
= (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
if (! b->uri) {
-@@ -3556,7 +3858,7 @@
+@@ -3556,7 +3984,7 @@
const char **endPtr) {
enum XML_Error result
= doCdataSection(parser, parser->m_encoding, &start, end, endPtr,
@@ -1230,7 +1388,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result != XML_ERROR_NONE)
return result;
if (start) {
-@@ -3576,7 +3878,8 @@
+@@ -3576,7 +4004,8 @@
*/
static enum XML_Error
doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
@@ -1240,7 +1398,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
const char *s = *startPtr;
const char **eventPP;
const char **eventEndPP;
-@@ -3594,6 +3897,12 @@
+@@ -3594,6 +4023,12 @@
for (;;) {
const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */
int tok = XmlCdataSectionTok(enc, s, end, &next);
@@ -1253,7 +1411,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
*eventEndPP = next;
switch (tok) {
case XML_TOK_CDATA_SECT_CLOSE:
-@@ -3738,6 +4047,13 @@
+@@ -3738,6 +4173,13 @@
*eventPP = s;
*startPtr = NULL;
tok = XmlIgnoreSectionTok(enc, s, end, &next);
@@ -1267,7 +1425,16 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
*eventEndPP = next;
switch (tok) {
case XML_TOK_IGNORE_SECT:
-@@ -3822,6 +4138,15 @@
+@@ -3787,7 +4229,7 @@
+ const char *s;
+ #ifdef XML_UNICODE
+ char encodingBuf[128];
+- /* See comments abount `protoclEncodingName` in parserInit() */
++ /* See comments about `protocolEncodingName` in parserInit() */
+ if (! parser->m_protocolEncodingName)
+ s = NULL;
+ else {
+@@ -3822,6 +4264,15 @@
const char *versionend;
const XML_Char *storedversion = NULL;
int standalone = -1;
@@ -1283,7 +1450,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
&version, &versionend, &encodingName, &newEncoding, &standalone)) {
-@@ -3971,6 +4296,10 @@
+@@ -3971,6 +4422,10 @@
for (;;) {
tok = XmlPrologTok(parser->m_encoding, start, end, &next);
@@ -1294,7 +1461,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
parser->m_eventEndPtr = next;
if (tok <= 0) {
if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
-@@ -3989,7 +4318,8 @@
+@@ -3989,7 +4444,8 @@
break;
}
/* found end of entity value - can store it now */
@@ -1304,7 +1471,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
} else if (tok == XML_TOK_XML_DECL) {
enum XML_Error result;
result = processXmlDecl(parser, 0, start, next);
-@@ -4016,6 +4346,14 @@
+@@ -4016,6 +4472,14 @@
*/
else if (tok == XML_TOK_BOM && next == end
&& ! parser->m_parsingStatus.finalBuffer) {
@@ -1319,7 +1486,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
*nextPtr = next;
return XML_ERROR_NONE;
}
-@@ -4058,16 +4396,24 @@
+@@ -4058,16 +4522,24 @@
}
/* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
However, when parsing an external subset, doProlog will not accept a BOM
@@ -1346,7 +1513,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
}
static enum XML_Error PTRCALL
-@@ -4080,6 +4426,9 @@
+@@ -4080,6 +4552,9 @@
for (;;) {
tok = XmlPrologTok(enc, start, end, &next);
@@ -1356,7 +1523,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (tok <= 0) {
if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
*nextPtr = s;
-@@ -4097,7 +4446,7 @@
+@@ -4097,7 +4572,7 @@
break;
}
/* found end of entity value - can store it now */
@@ -1365,7 +1532,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
}
start = next;
}
-@@ -4111,13 +4460,14 @@
+@@ -4111,13 +4586,14 @@
const char *next = s;
int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
@@ -1382,7 +1549,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
#ifdef XML_DTD
static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
#endif /* XML_DTD */
-@@ -4144,6 +4494,10 @@
+@@ -4144,6 +4620,10 @@
static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
@@ -1393,7 +1560,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
/* save one level of indirection */
DTD *const dtd = parser->m_dtd;
-@@ -4208,6 +4562,19 @@
+@@ -4208,6 +4688,19 @@
}
}
role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
@@ -1413,7 +1580,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
switch (role) {
case XML_ROLE_XML_DECL: {
enum XML_Error result = processXmlDecl(parser, 0, s, next);
-@@ -4483,7 +4850,8 @@
+@@ -4483,7 +4976,8 @@
const XML_Char *attVal;
enum XML_Error result = storeAttributeValue(
parser, enc, parser->m_declAttributeIsCdata,
@@ -1423,7 +1590,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result)
return result;
attVal = poolStart(&dtd->pool);
-@@ -4516,8 +4884,9 @@
+@@ -4516,8 +5010,9 @@
break;
case XML_ROLE_ENTITY_VALUE:
if (dtd->keepProcessing) {
@@ -1435,7 +1602,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (parser->m_declEntity) {
parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
parser->m_declEntity->textLen
-@@ -4776,7 +5145,13 @@
+@@ -4776,7 +5271,13 @@
if (parser->m_prologState.level >= parser->m_groupSize) {
if (parser->m_groupSize) {
{
@@ -1450,7 +1617,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
parser, parser->m_groupConnector, parser->m_groupSize *= 2);
if (new_connector == NULL) {
parser->m_groupSize /= 2;
-@@ -4786,7 +5161,18 @@
+@@ -4786,7 +5287,18 @@
}
if (dtd->scaffIndex) {
@@ -1470,7 +1637,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
if (new_scaff_index == NULL)
return XML_ERROR_NO_MEMORY;
-@@ -4907,12 +5293,15 @@
+@@ -4907,12 +5419,15 @@
if (parser->m_externalEntityRefHandler) {
dtd->paramEntityRead = XML_FALSE;
entity->open = XML_TRUE;
@@ -1486,7 +1653,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
entity->open = XML_FALSE;
handleDefault = XML_FALSE;
if (! dtd->paramEntityRead) {
-@@ -4991,7 +5380,7 @@
+@@ -4991,7 +5506,7 @@
if (dtd->in_eldecl) {
ELEMENT_TYPE *el;
const XML_Char *name;
@@ -1495,7 +1662,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
const char *nxt
= (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
int myindex = nextScaffoldPart(parser);
-@@ -5007,7 +5396,13 @@
+@@ -5007,7 +5522,13 @@
nameLen = 0;
for (; name[nameLen++];)
;
@@ -1510,7 +1677,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (parser->m_elementDeclHandler)
handleDefault = XML_FALSE;
}
-@@ -5110,6 +5505,13 @@
+@@ -5110,6 +5631,13 @@
for (;;) {
const char *next = NULL;
int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
@@ -1524,7 +1691,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
parser->m_eventEndPtr = next;
switch (tok) {
/* report partial linebreak - it might be the last token */
-@@ -5183,6 +5585,9 @@
+@@ -5183,6 +5711,9 @@
return XML_ERROR_NO_MEMORY;
}
entity->open = XML_TRUE;
@@ -1534,7 +1701,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
entity->processed = 0;
openEntity->next = parser->m_openInternalEntities;
parser->m_openInternalEntities = openEntity;
-@@ -5201,17 +5606,22 @@
+@@ -5201,17 +5732,22 @@
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
@@ -1559,7 +1726,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
/* put openEntity back in list of free instances */
-@@ -5244,12 +5654,13 @@
+@@ -5244,12 +5780,13 @@
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
@@ -1575,7 +1742,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result != XML_ERROR_NONE)
return result;
-@@ -5258,6 +5669,9 @@
+@@ -5258,6 +5795,9 @@
entity->processed = (int)(next - (const char *)entity->textPtr);
return result;
} else {
@@ -1585,7 +1752,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
/* put openEntity back in list of free instances */
-@@ -5271,7 +5685,8 @@
+@@ -5271,7 +5811,8 @@
parser->m_processor = prologProcessor;
tok = XmlPrologTok(parser->m_encoding, s, end, &next);
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
@@ -1595,7 +1762,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
} else
#endif /* XML_DTD */
{
-@@ -5279,7 +5694,8 @@
+@@ -5279,7 +5820,8 @@
/* see externalEntityContentProcessor vs contentProcessor */
return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
s, end, nextPtr,
@@ -1605,7 +1772,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
}
}
-@@ -5294,9 +5710,10 @@
+@@ -5294,9 +5836,10 @@
static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
@@ -1618,7 +1785,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (result)
return result;
if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
-@@ -5308,11 +5725,23 @@
+@@ -5308,11 +5851,23 @@
static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
@@ -1644,7 +1811,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
switch (tok) {
case XML_TOK_NONE:
return XML_ERROR_NONE;
-@@ -5372,6 +5801,14 @@
+@@ -5372,6 +5927,14 @@
XML_Char ch = (XML_Char)XmlPredefinedEntityName(
enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
if (ch) {
@@ -1659,7 +1826,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (! poolAppendChar(pool, ch))
return XML_ERROR_NO_MEMORY;
break;
-@@ -5449,9 +5886,16 @@
+@@ -5449,9 +6012,16 @@
enum XML_Error result;
const XML_Char *textEnd = entity->textPtr + entity->textLen;
entity->open = XML_TRUE;
@@ -1677,7 +1844,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
entity->open = XML_FALSE;
if (result)
return result;
-@@ -5481,13 +5925,16 @@
+@@ -5481,13 +6051,16 @@
static enum XML_Error
storeEntityValue(XML_Parser parser, const ENCODING *enc,
@@ -1695,7 +1862,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
#endif /* XML_DTD */
/* never return Null for the value argument in EntityDeclHandler,
since this would indicate an external entity; therefore we
-@@ -5498,8 +5945,19 @@
+@@ -5498,8 +6071,19 @@
}
for (;;) {
@@ -1716,7 +1883,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
switch (tok) {
case XML_TOK_PARAM_ENTITY_REF:
#ifdef XML_DTD
-@@ -5535,13 +5993,16 @@
+@@ -5535,13 +6119,16 @@
if (parser->m_externalEntityRefHandler) {
dtd->paramEntityRead = XML_FALSE;
entity->open = XML_TRUE;
@@ -1733,7 +1900,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
entity->open = XML_FALSE;
if (! dtd->paramEntityRead)
dtd->keepProcessing = dtd->standalone;
-@@ -5549,9 +6010,12 @@
+@@ -5549,9 +6136,12 @@
dtd->keepProcessing = dtd->standalone;
} else {
entity->open = XML_TRUE;
@@ -1747,7 +1914,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
entity->open = XML_FALSE;
if (result)
goto endEntityValue;
-@@ -5784,7 +6248,25 @@
+@@ -5784,7 +6374,25 @@
}
} else {
DEFAULT_ATTRIBUTE *temp;
@@ -1774,7 +1941,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
(count * sizeof(DEFAULT_ATTRIBUTE)));
if (temp == NULL)
-@@ -6435,10 +6917,26 @@
+@@ -6435,10 +7043,26 @@
/* check for overflow (table is half full) */
if (table->used >> (table->power - 1)) {
unsigned char newPower = table->power + 1;
@@ -1805,7 +1972,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
if (! newV)
return NULL;
memset(newV, 0, tsize);
-@@ -6786,6 +7284,20 @@
+@@ -6786,6 +7410,20 @@
if (dtd->scaffCount >= dtd->scaffSize) {
CONTENT_SCAFFOLD *temp;
if (dtd->scaffold) {
@@ -1826,7 +1993,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
temp = (CONTENT_SCAFFOLD *)REALLOC(
parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
if (temp == NULL)
-@@ -6817,55 +7329,130 @@
+@@ -6817,55 +7455,134 @@
return next;
}
@@ -1864,6 +2031,10 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
-
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;
@@ -1996,7 +2167,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
return ret;
}
-@@ -6894,7 +7481,7 @@
+@@ -6894,7 +7611,7 @@
static XML_Char *
copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
@@ -2005,7 +2176,7 @@ diff -ru misc/expat-2.2.10/lib/xmlparse.c misc/build/expat-2.2.10/lib/xmlparse.c
XML_Char *result;
/* First determine how long the string is */
-@@ -6912,3 +7499,766 @@
+@@ -6912,3 +7629,766 @@
memcpy(result, s, charsRequired * sizeof(XML_Char));
return result;
}
@@ -2954,7 +3125,7 @@ diff -ru misc/expat-2.2.10/tests/minicheck.c misc/build/expat-2.2.10/tests/minic
fprintf(stderr, "ERROR: %s%s", msg, has_newline ? "" : "\n");
diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtests.c
--- misc/expat-2.2.10/tests/runtests.c 2020-10-03 17:14:57.000000000 +0200
-+++ misc/build/expat-2.2.10/tests/runtests.c 2022-03-05 12:25:27.583396678 +0100
++++ misc/build/expat-2.2.10/tests/runtests.c 2022-03-09 20:25:36.716575629 +0100
@@ -45,6 +45,7 @@
#include <stddef.h> /* ptrdiff_t */
#include <ctype.h>
@@ -2972,7 +3143,307 @@ diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtes
#include "minicheck.h"
#include "memcheck.h"
#include "siphash.h"
-@@ -11231,6 +11232,381 @@
+@@ -2677,6 +2678,82 @@
+ }
+ END_TEST
+
++static void XMLCALL
++element_decl_check_model(void *userData, const XML_Char *name,
++ XML_Content *model) {
++ uint32_t errorFlags = 0;
++ UNUSED_P(userData);
++
++ /* Expected model array structure is this:
++ * [0] (type 6, quant 0)
++ * [1] (type 5, quant 0)
++ * [3] (type 4, quant 0, name "bar")
++ * [4] (type 4, quant 0, name "foo")
++ * [5] (type 4, quant 3, name "xyz")
++ * [2] (type 4, quant 2, name "zebra")
++ */
++ errorFlags |= ((xcstrcmp(name, XCS("junk")) == 0) ? 0 : (1u << 0));
++ errorFlags |= ((model != NULL) ? 0 : (1u << 1));
++
++ errorFlags |= ((model[0].type == XML_CTYPE_SEQ) ? 0 : (1u << 2));
++ errorFlags |= ((model[0].quant == XML_CQUANT_NONE) ? 0 : (1u << 3));
++ errorFlags |= ((model[0].numchildren == 2) ? 0 : (1u << 4));
++ errorFlags |= ((model[0].children == &model[1]) ? 0 : (1u << 5));
++ errorFlags |= ((model[0].name == NULL) ? 0 : (1u << 6));
++
++ errorFlags |= ((model[1].type == XML_CTYPE_CHOICE) ? 0 : (1u << 7));
++ errorFlags |= ((model[1].quant == XML_CQUANT_NONE) ? 0 : (1u << 8));
++ errorFlags |= ((model[1].numchildren == 3) ? 0 : (1u << 9));
++ errorFlags |= ((model[1].children == &model[3]) ? 0 : (1u << 10));
++ errorFlags |= ((model[1].name == NULL) ? 0 : (1u << 11));
++
++ errorFlags |= ((model[2].type == XML_CTYPE_NAME) ? 0 : (1u << 12));
++ errorFlags |= ((model[2].quant == XML_CQUANT_REP) ? 0 : (1u << 13));
++ errorFlags |= ((model[2].numchildren == 0) ? 0 : (1u << 14));
++ errorFlags |= ((model[2].children == NULL) ? 0 : (1u << 15));
++ errorFlags |= ((xcstrcmp(model[2].name, XCS("zebra")) == 0) ? 0 : (1u << 16));
++
++ errorFlags |= ((model[3].type == XML_CTYPE_NAME) ? 0 : (1u << 17));
++ errorFlags |= ((model[3].quant == XML_CQUANT_NONE) ? 0 : (1u << 18));
++ errorFlags |= ((model[3].numchildren == 0) ? 0 : (1u << 19));
++ errorFlags |= ((model[3].children == NULL) ? 0 : (1u << 20));
++ errorFlags |= ((xcstrcmp(model[3].name, XCS("bar")) == 0) ? 0 : (1u << 21));
++
++ errorFlags |= ((model[4].type == XML_CTYPE_NAME) ? 0 : (1u << 22));
++ errorFlags |= ((model[4].quant == XML_CQUANT_NONE) ? 0 : (1u << 23));
++ errorFlags |= ((model[4].numchildren == 0) ? 0 : (1u << 24));
++ errorFlags |= ((model[4].children == NULL) ? 0 : (1u << 25));
++ errorFlags |= ((xcstrcmp(model[4].name, XCS("foo")) == 0) ? 0 : (1u << 26));
++
++ errorFlags |= ((model[5].type == XML_CTYPE_NAME) ? 0 : (1u << 27));
++ errorFlags |= ((model[5].quant == XML_CQUANT_PLUS) ? 0 : (1u << 28));
++ errorFlags |= ((model[5].numchildren == 0) ? 0 : (1u << 29));
++ errorFlags |= ((model[5].children == NULL) ? 0 : (1u << 30));
++ errorFlags |= ((xcstrcmp(model[5].name, XCS("xyz")) == 0) ? 0 : (1u << 31));
++
++ XML_SetUserData(g_parser, (void *)(uintptr_t)errorFlags);
++ XML_FreeContentModel(g_parser, model);
++}
++
++START_TEST(test_dtd_elements_nesting) {
++ // Payload inspired by a test in Perl's XML::Parser
++ const char *text = "<!DOCTYPE foo [\n"
++ "<!ELEMENT junk ((bar|foo|xyz+), zebra*)>\n"
++ "]>\n"
++ "<foo/>";
++
++ XML_SetUserData(g_parser, (void *)(uintptr_t)-1);
++
++ XML_SetElementDeclHandler(g_parser, element_decl_check_model);
++ if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
++ == XML_STATUS_ERROR)
++ xml_failure(g_parser);
++
++ if ((uint32_t)(uintptr_t)XML_GetUserData(g_parser) != 0)
++ fail("Element declaration model regression detected");
++}
++END_TEST
++
+ /* Test foreign DTD handling */
+ START_TEST(test_set_foreign_dtd) {
+ const char *text1 = "<?xml version='1.0' encoding='us-ascii'?>\n";
+@@ -3860,6 +3937,30 @@
+ }
+ END_TEST
+
++/* Test for signed integer overflow CVE-2022-23852 */
++#if defined(XML_CONTEXT_BYTES)
++START_TEST(test_get_buffer_3_overflow) {
++ XML_Parser parser = XML_ParserCreate(NULL);
++
++ const char *const text = "\n";
++ const int expectedKeepValue = (int)strlen(text);
++
++ assert(parser != NULL);
++ // After this call, variable "keep" in XML_GetBuffer will
++ // have value expectedKeepValue
++ if (XML_Parse(parser, text, (int)strlen(text), XML_FALSE /* isFinal */)
++ == XML_STATUS_ERROR)
++ xml_failure(parser);
++
++ assert(expectedKeepValue > 0);
++ if (XML_GetBuffer(parser, INT_MAX - expectedKeepValue + 1) != NULL)
++ fail("enlarging buffer not failed");
++
++ XML_ParserFree(parser);
++}
++END_TEST
++#endif // defined(XML_CONTEXT_BYTES)
++
+ /* Test position information macros */
+ START_TEST(test_byte_info_at_end) {
+ const char *text = "<doc></doc>";
+@@ -5987,6 +6088,107 @@
+ }
+ END_TEST
+
++START_TEST(test_utf8_in_start_tags) {
++ struct test_case {
++ bool goodName;
++ bool goodNameStart;
++ const char *tagName;
++ };
++
++ // The idea with the tests below is this:
++ // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences
++ // go to isNever and are hence not a concern.
++ //
++ // We start with a character that is a valid name character
++ // (or even name-start character, see XML 1.0r4 spec) and then we flip
++ // single bits at places where (1) the result leaves the UTF-8 encoding space
++ // and (2) we stay in the same n-byte sequence family.
++ //
++ // The flipped bits are highlighted in angle brackets in comments,
++ // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped
++ // the most significant bit to 1 to leave UTF-8 encoding space.
++ struct test_case cases[] = {
++ // 1-byte UTF-8: [0xxx xxxx]
++ {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':'
++ {false, false, "\xBA"}, // [<1>011 1010]
++ {true, false, "\x39"}, // [0011 1001] = ASCII nine '9'
++ {false, false, "\xB9"}, // [<1>011 1001]
++
++ // 2-byte UTF-8: [110x xxxx] [10xx xxxx]
++ {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] =
++ // Arabic small waw U+06E5
++ {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101]
++ {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101]
++ {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101]
++ {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] =
++ // combining char U+0301
++ {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001]
++ {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001]
++ {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001]
++
++ // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx]
++ {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] =
++ // Devanagari Letter A U+0905
++ {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101]
++ {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101]
++ {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101]
++ {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101]
++ {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101]
++ {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] =
++ // combining char U+0901
++ {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001]
++ {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001]
++ {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001]
++ {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001]
++ {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001]
++ };
++ const bool atNameStart[] = {true, false};
++
++ size_t i = 0;
++ char doc[1024];
++ size_t failCount = 0;
++
++ for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
++ size_t j = 0;
++ for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) {
++ const bool expectedSuccess
++ = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName;
++ XML_Parser parser = XML_ParserCreate(NULL);
++ enum XML_Status status;
++ bool success;
++ sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName);
++
++ status
++ = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE);
++
++ success = true;
++ if ((status == XML_STATUS_OK) != expectedSuccess) {
++ success = false;
++ }
++ if ((status == XML_STATUS_ERROR)
++ && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) {
++ success = false;
++ }
++
++ if (! success) {
++ fprintf(
++ stderr,
++ "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n",
++ (unsigned)i + 1u, atNameStart[j] ? " " : "not ",
++ (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser));
++ failCount++;
++ }
++
++ XML_ParserFree(parser);
++ }
++ }
++
++ if (failCount > 0) {
++ fail("UTF-8 regression detected");
++ }
++}
++END_TEST
++
+ /* Test trailing spaces in elements are accepted */
+ static void XMLCALL
+ record_element_end_handler(void *userData, const XML_Char *name) {
+@@ -6164,6 +6366,14 @@
+ }
+ END_TEST
+
++START_TEST(test_bad_doctype_utf8) {
++ const char *text = "<!DOCTYPE \xDB\x25"
++ "doc><doc/>"; // [1101 1011] [<0>010 0101]
++ expect_failure(text, XML_ERROR_INVALID_TOKEN,
++ "Invalid UTF-8 in DOCTYPE not faulted");
++}
++END_TEST
++
+ START_TEST(test_bad_doctype_utf16) {
+ const char text[] =
+ /* <!DOCTYPE doc [ \x06f2 ]><doc/>
+@@ -7209,6 +7419,37 @@
+ }
+ END_TEST
+
++START_TEST(test_ns_separator_in_uri) {
++ struct test_case {
++ enum XML_Status expectedStatus;
++ const char *doc;
++ XML_Char namesep;
++ };
++ struct test_case cases[] = {
++ {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')},
++ {XML_STATUS_ERROR, "<doc xmlns='one
two' />", XCS('\n')},
++ {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')},
++ };
++
++ size_t i = 0;
++ size_t failCount = 0;
++ for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
++ XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep);
++ XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
++ if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
++ /*isFinal*/ XML_TRUE)
++ != cases[i].expectedStatus) {
++ failCount++;
++ }
++ XML_ParserFree(parser);
++ }
++
++ if (failCount) {
++ fail("Namespace separator handling is broken");
++ }
++}
++END_TEST
++
+ /* Control variable; the number of times duff_allocator() will successfully
+ * allocate */
+ #define ALLOC_ALWAYS_SUCCEED (-1)
+@@ -7365,7 +7606,7 @@
+ fail("Version mismatch");
+
+ #if ! defined(XML_UNICODE) || defined(XML_UNICODE_WCHAR_T)
+- if (xcstrcmp(version_text, XCS("expat_2.2.10"))) /* needs bump on releases */
++ if (xcstrcmp(version_text, XCS("expat_2.2.13"))) /* needs bump on releases */
+ fail("XML_*_VERSION in expat.h out of sync?\n");
+ #else
+ /* If we have XML_UNICODE defined but not XML_UNICODE_WCHAR_T
+@@ -9851,6 +10092,15 @@
+
+ /* Try a parse before the start of the world */
+ /* (Exercises new code path) */
++ if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
++ fail("Pre-init XML_ParseBuffer not faulted");
++ if (XML_GetErrorCode(g_parser) != XML_ERROR_NO_BUFFER)
++ fail("Pre-init XML_ParseBuffer faulted for wrong reason");
++
++ buffer = XML_GetBuffer(g_parser, 1 /* any small number greater than 0 */);
++ if (buffer == NULL)
++ fail("Could not acquire parse buffer");
++
+ allocation_count = 0;
+ if (XML_ParseBuffer(g_parser, 0, XML_FALSE) != XML_STATUS_ERROR)
+ fail("Pre-init XML_ParseBuffer not faulted");
+@@ -11231,6 +11481,401 @@
}
END_TEST
@@ -3068,6 +3539,16 @@ diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtes
+
+ /* CDATA */
+ {"<e><![CDATA[one two three]]></e>", NULL, NULL, 0, filled_later},
++ /* The following is the essence of this OSS-Fuzz finding:
++ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34302
++ https://oss-fuzz.com/testcase-detail/4860575394955264
++ */
++ {"<!DOCTYPE r [\n"
++ "<!ENTITY e \"111<![CDATA[2 <= 2]]>333\">\n"
++ "]>\n"
++ "<r>&e;</r>\n",
++ NULL, NULL, sizeof(XML_Char) * strlen("111<![CDATA[2 <= 2]]>333"),
++ filled_later},
+
+ /* Conditional sections */
+ {"<!DOCTYPE r [\n"
@@ -3265,6 +3746,16 @@ diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtes
+}
+END_TEST
+
++static float
++portableNAN() {
++ return strtof("nan", NULL);
++}
++
++static float
++portableINFINITY() {
++ return strtof("infinity", NULL);
++}
++
+START_TEST(test_billion_laughs_attack_protection_api) {
+ XML_Parser parserWithoutParent = XML_ParserCreate(NULL);
+ XML_Parser parserWithParent
@@ -3283,7 +3774,7 @@ diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtes
+ == XML_TRUE)
+ fail("Call with non-root parser is NOT supposed to succeed");
+ if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
-+ parserWithoutParent, NAN)
++ parserWithoutParent, portableNAN())
+ == XML_TRUE)
+ fail("Call with NaN limit is NOT supposed to succeed");
+ if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
@@ -3305,7 +3796,7 @@ diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtes
+ == XML_FALSE)
+ fail("Call with positive limit >=1.0 is supposed to succeed");
+ if (XML_SetBillionLaughsAttackProtectionMaximumAmplification(
-+ parserWithoutParent, INFINITY)
++ parserWithoutParent, portableINFINITY())
+ == XML_FALSE)
+ fail("Call with positive limit >=1.0 is supposed to succeed");
+
@@ -3354,7 +3845,7 @@ diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtes
static Suite *
make_suite(void) {
Suite *s = suite_create("basic");
-@@ -11239,6 +11615,9 @@
+@@ -11239,6 +11884,9 @@
TCase *tc_misc = tcase_create("miscellaneous tests");
TCase *tc_alloc = tcase_create("allocation tests");
TCase *tc_nsalloc = tcase_create("namespace allocation tests");
@@ -3364,7 +3855,49 @@ diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtes
suite_add_tcase(s, tc_basic);
tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
-@@ -11603,6 +11982,13 @@
+@@ -11325,6 +11973,7 @@
+ tcase_add_test(tc_basic, test_memory_allocation);
+ tcase_add_test(tc_basic, test_default_current);
+ tcase_add_test(tc_basic, test_dtd_elements);
++ tcase_add_test(tc_basic, test_dtd_elements_nesting);
+ tcase_add_test__ifdef_xml_dtd(tc_basic, test_set_foreign_dtd);
+ tcase_add_test__ifdef_xml_dtd(tc_basic, test_foreign_dtd_not_standalone);
+ tcase_add_test__ifdef_xml_dtd(tc_basic, test_invalid_foreign_dtd);
+@@ -11353,6 +12002,9 @@
+ tcase_add_test(tc_basic, test_empty_parse);
+ tcase_add_test(tc_basic, test_get_buffer_1);
+ tcase_add_test(tc_basic, test_get_buffer_2);
++#if defined(XML_CONTEXT_BYTES)
++ tcase_add_test(tc_basic, test_get_buffer_3_overflow);
++#endif
+ tcase_add_test(tc_basic, test_byte_info_at_end);
+ tcase_add_test(tc_basic, test_byte_info_at_error);
+ tcase_add_test(tc_basic, test_byte_info_at_cdata);
+@@ -11436,6 +12088,7 @@
+ tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
+ tcase_add_test(tc_basic, test_utf8_in_cdata_section);
+ tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
++ tcase_add_test(tc_basic, test_utf8_in_start_tags);
+ tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
+ tcase_add_test(tc_basic, test_utf16_attribute);
+ tcase_add_test(tc_basic, test_utf16_second_attr);
+@@ -11444,6 +12097,7 @@
+ tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
+ tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
+ tcase_add_test(tc_basic, test_bad_doctype);
++ tcase_add_test(tc_basic, test_bad_doctype_utf8);
+ tcase_add_test(tc_basic, test_bad_doctype_utf16);
+ tcase_add_test(tc_basic, test_bad_doctype_plus);
+ tcase_add_test(tc_basic, test_bad_doctype_star);
+@@ -11500,6 +12154,7 @@
+ tcase_add_test(tc_namespace, test_ns_utf16_doctype);
+ tcase_add_test(tc_namespace, test_ns_invalid_doctype);
+ tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
++ tcase_add_test(tc_namespace, test_ns_separator_in_uri);
+
+ suite_add_tcase(s, tc_misc);
+ tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
+@@ -11603,6 +12258,13 @@
tcase_add_test(tc_nsalloc, test_nsalloc_long_systemid_in_ext);
tcase_add_test(tc_nsalloc, test_nsalloc_prefixed_element);
@@ -3378,6 +3911,18 @@ diff -ru misc/expat-2.2.10/tests/runtests.c misc/build/expat-2.2.10/tests/runtes
return s;
}
+diff -ru misc/expat-2.2.10/win32/expat.iss misc/build/expat-2.2.10/win32/expat.iss
+--- misc/expat-2.2.10/win32/expat.iss 2020-10-03 17:14:57.000000000 +0200
++++ misc/build/expat-2.2.10/win32/expat.iss 2022-03-09 20:25:36.720575719 +0100
+@@ -4,7 +4,7 @@
+ ; This script was contributed by Tim Peters.
+ ; It was designed for Inno Setup 2.0.19 but works with later versions as well.
+
+-#define expatVer "2.2.10"
++#define expatVer "2.2.13"
+
+ [Setup]
+ AppName=Expat
diff -ru misc/expat-2.2.10/xmlwf/Makefile.in misc/build/expat-2.2.10/xmlwf/Makefile.in
--- misc/expat-2.2.10/xmlwf/Makefile.in 2020-10-03 17:37:06.000000000 +0200
+++ misc/build/expat-2.2.10/xmlwf/Makefile.in 2022-03-05 12:25:27.583396678 +0100
@@ -3401,7 +3946,7 @@ diff -ru misc/expat-2.2.10/xmlwf/Makefile.in misc/build/expat-2.2.10/xmlwf/Makef
srcdir = @srcdir@
diff -ru misc/expat-2.2.10/xmlwf/xmltchar.h misc/build/expat-2.2.10/xmlwf/xmltchar.h
--- misc/expat-2.2.10/xmlwf/xmltchar.h 2020-09-25 19:47:39.000000000 +0200
-+++ misc/build/expat-2.2.10/xmlwf/xmltchar.h 2022-03-05 12:25:27.583396678 +0100
++++ misc/build/expat-2.2.10/xmlwf/xmltchar.h 2022-03-09 20:25:36.720575719 +0100
@@ -54,6 +54,8 @@
# define tmain wmain
# define tremove _wremove
@@ -3420,7 +3965,7 @@ diff -ru misc/expat-2.2.10/xmlwf/xmltchar.h misc/build/expat-2.2.10/xmlwf/xmltch
#endif /* not XML_UNICODE */
diff -ru misc/expat-2.2.10/xmlwf/xmlwf.c misc/build/expat-2.2.10/xmlwf/xmlwf.c
--- misc/expat-2.2.10/xmlwf/xmlwf.c 2020-09-25 19:47:39.000000000 +0200
-+++ misc/build/expat-2.2.10/xmlwf/xmlwf.c 2022-03-05 12:25:27.583396678 +0100
++++ misc/build/expat-2.2.10/xmlwf/xmlwf.c 2022-03-09 20:25:36.720575719 +0100
@@ -30,11 +30,15 @@
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
@@ -3452,7 +3997,43 @@ diff -ru misc/expat-2.2.10/xmlwf/xmlwf.c misc/build/expat-2.2.10/xmlwf/xmlwf.c
/* Structures for handler user data */
typedef struct NotationList {
struct NotationList *next;
-@@ -875,6 +887,12 @@
+@@ -322,6 +334,13 @@
+ data->notationListHead = NULL;
+ }
+
++static void
++cleanupUserData(XmlwfUserData *userData) {
++ free((void *)userData->currentDoctypeName);
++ userData->currentDoctypeName = NULL;
++ freeNotations(userData);
++}
++
+ static int
+ xcscmp(const XML_Char *xs, const XML_Char *xt) {
+ while (*xs != 0 && *xt != 0) {
+@@ -850,9 +869,10 @@
+ * $ xmlwf/xmlwf_helpgen.sh
+ */
+ /* clang-format off */
+- T("usage: %s [-s] [-n] [-p] [-x] [-e ENCODING] [-w] [-r] [-d DIRECTORY]\n")
+- T(" [-c | -m | -t] [-N]\n")
+- T(" [FILE [FILE ...]]\n")
++ T("usage:\n")
++ T(" %s [OPTIONS] [FILE ...]\n")
++ T(" %s -h\n")
++ T(" %s -v\n")
+ T("\n")
+ T("xmlwf - Determines if an XML document is well-formed\n")
+ T("\n")
+@@ -867,6 +887,7 @@
+ T(" -e ENCODING override any in-document [e]ncoding declaration\n")
+ T(" -w enable support for [W]indows code pages\n")
+ T(" -r disable memory-mapping and use normal file [r]ead IO calls instead\n")
++ T(" -k when processing multiple files, [k]eep processing after first file with error\n")
+ T("\n")
+ T("output control arguments:\n")
+ T(" -d DIRECTORY output [d]estination directory\n")
+@@ -875,14 +896,27 @@
T(" -t write no XML output for [t]iming of plain parsing\n")
T(" -N enable adding doctype and [n]otation declarations\n")
T("\n")
@@ -3465,7 +4046,23 @@ diff -ru misc/expat-2.2.10/xmlwf/xmlwf.c misc/build/expat-2.2.10/xmlwf/xmlwf.c
T("info arguments:\n")
T(" -h show this [h]elp message and exit\n")
T(" -v show program's [v]ersion number and exit\n")
-@@ -891,6 +909,19 @@
+ T("\n")
++ T("exit status:\n")
++ T(" 0 the input files are well-formed and the output (if requested) was written successfully\n")
++ T(" 1 could not allocate data structures, signals a serious problem with execution environment\n")
++ T(" 2 one or more input files were not well-formed\n")
++ T(" 3 could not create an output file\n")
++ T(" 4 command-line argument error\n")
++ T("\n")
+ T("xmlwf of libexpat is software libre, licensed under the MIT license.\n")
+ T("Please report bugs at https://github.com/libexpat/libexpat/issues. Thank you!\n")
+ , /* clang-format on */
+- prog);
++ prog, prog, prog);
+ exit(rc);
+ }
+
+@@ -891,6 +925,19 @@
int wmain(int argc, XML_Char **argv);
#endif
@@ -3485,22 +4082,56 @@ diff -ru misc/expat-2.2.10/xmlwf/xmlwf.c misc/build/expat-2.2.10/xmlwf/xmlwf.c
int
tmain(int argc, XML_Char **argv) {
int i, j;
-@@ -902,6 +933,11 @@
+@@ -902,6 +949,13 @@
int useNamespaces = 0;
int requireStandalone = 0;
int requiresNotations = 0;
++ int continueOnError = 0;
+
+ float attackMaximumAmplification = -1.0f; /* signaling "not set" */
+ unsigned long long attackThresholdBytes;
+ XML_Bool attackThresholdGiven = XML_FALSE;
+
++ int exitCode = XMLWF_EXIT_SUCCESS;
enum XML_ParamEntityParsing paramEntityParsing
= XML_PARAM_ENTITY_PARSING_NEVER;
int useStdin = 0;
-@@ -990,6 +1026,49 @@
+@@ -965,31 +1019,64 @@
+ j++;
+ break;
+ case T('d'):
+- if (argv[i][j + 1] == T('\0')) {
+- if (++i == argc)
+- usage(argv[0], 2);
+- outputDir = argv[i];
+- } else
+- outputDir = argv[i] + j + 1;
+- i++;
+- j = 0;
++ XMLWF_SHIFT_ARG_INTO(outputDir, argc, argv, i, j);
+ break;
+ case T('e'):
+- if (argv[i][j + 1] == T('\0')) {
+- if (++i == argc)
+- usage(argv[0], 2);
+- encoding = argv[i];
+- } else
+- encoding = argv[i] + j + 1;
+- i++;
+- j = 0;
++ XMLWF_SHIFT_ARG_INTO(encoding, argc, argv, i, j);
+ break;
+ case T('h'):
+- usage(argv[0], 0);
++ usage(argv[0], XMLWF_EXIT_SUCCESS);
+ return 0;
case T('v'):
showVersion(argv[0]);
return 0;
++ case T('k'):
++ continueOnError = 1;
++ j++;
++ break;
+ case T('a'): {
+ const XML_Char *valueText = NULL;
+ XMLWF_SHIFT_ARG_INTO(valueText, argc, argv, i, j);
@@ -3547,10 +4178,23 @@ diff -ru misc/expat-2.2.10/xmlwf/xmlwf.c misc/build/expat-2.2.10/xmlwf/xmlwf.c
case T('\0'):
if (j > 1) {
i++;
-@@ -1020,6 +1099,19 @@
- exit(1);
+@@ -998,7 +1085,7 @@
+ }
+ /* fall through */
+ default:
+- usage(argv[0], 2);
++ usage(argv[0], XMLWF_EXIT_USAGE_ERROR);
}
+ }
+ if (i == argc) {
+@@ -1017,7 +1104,22 @@
+ if (! parser) {
+ tperror(T("Could not instantiate parser"));
+- exit(1);
++ exit(XMLWF_EXIT_INTERNAL_ERROR);
++ }
++
+ if (attackMaximumAmplification != -1.0f) {
+#ifdef XML_DTD
+ XML_SetBillionLaughsAttackProtectionMaximumAmplification(
@@ -3561,12 +4205,52 @@ diff -ru misc/expat-2.2.10/xmlwf/xmlwf.c misc/build/expat-2.2.10/xmlwf/xmlwf.c
+#ifdef XML_DTD
+ XML_SetBillionLaughsAttackProtectionActivationThreshold(
+ parser, attackThresholdBytes);
++#else
++ (void)attackThresholdBytes; // silence -Wunused-but-set-variable
+#endif
-+ }
-+
+ }
+
if (requireStandalone)
- XML_SetNotStandaloneHandler(parser, notStandalone);
- XML_SetParamEntityParsing(parser, paramEntityParsing);
+@@ -1053,7 +1155,7 @@
+ * sizeof(XML_Char));
+ if (! outName) {
+ tperror(T("Could not allocate memory"));
+- exit(1);
++ exit(XMLWF_EXIT_INTERNAL_ERROR);
+ }
+ tcscpy(outName, outputDir);
+ tcscat(outName, delim);
+@@ -1061,7 +1163,14 @@
+ userData.fp = tfopen(outName, T("wb"));
+ if (! userData.fp) {
+ tperror(outName);
+- exit(3);
++ exitCode = XMLWF_EXIT_OUTPUT_ERROR;
++ free(outName);
++ XML_ParserFree(parser);
++ if (continueOnError) {
++ continue;
++ } else {
++ break;
++ }
+ }
+ setvbuf(userData.fp, NULL, _IOFBF, 16384);
+ #ifdef XML_UNICODE
+@@ -1123,8 +1232,12 @@
+ }
+ XML_ParserFree(parser);
+ if (! result) {
+- exit(2);
++ exitCode = XMLWF_EXIT_NOT_WELLFORMED;
++ cleanupUserData(&userData);
++ if (! continueOnError) {
++ break;
++ }
+ }
+ }
+- return 0;
++ return exitCode;
+ }
diff -ru misc/expat-2.2.10/xmlwf/xmlwf_helpgen.py misc/build/expat-2.2.10/xmlwf/xmlwf_helpgen.py
--- misc/expat-2.2.10/xmlwf/xmlwf_helpgen.py 2020-09-25 19:47:39.000000000 +0200
+++ misc/build/expat-2.2.10/xmlwf/xmlwf_helpgen.py 2022-03-05 12:25:27.583396678 +0100