untrusted comment: verify with openbsd-79-base.pub
RWTSdNN9A3yvWGk8OmqHhsc/fyxGQuCkx/b8rmFTVaHFYhT6GjO8i2HNSEmWWcXuT/HKxjqknVuocN7A8K5Eqi3dqEIzq2yWnww=
OpenBSD 7.9 errata 033, October 7, 2026:
Backport fixes from libexpat 2.8.5.
CVE-2026-93990
Apply by doing:
signify -Vep /etc/signify/openbsd-79-base.pub -x 033_expat.patch.sig \
-m - | (cd /usr/src && patch -p0)
And then rebuild and install libexpat:
cd /usr/src/lib/libexpat
make obj
make
make install
Index: lib/libexpat/Changes
===================================================================
RCS file: /cvs/src/lib/libexpat/Changes,v
diff -u -p -r1.35.2.2 Changes
--- lib/libexpat/Changes 10 Sep 2026 20:46:02 -0000 1.35.2.2
+++ lib/libexpat/Changes 2 Oct 2026 22:01:20 -0000
@@ -16,6 +16,33 @@
!! Sebastian Pipping -- Berlin, 2026-08-03 !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+Tue September 22 2026
+ Security fixes:
+ #1282 CVE-2026-93990 -- Reject high surrogates not followed by a
+ low surrogate during UTF-16 decoding; previously, malformed
+ UTF-16 could be smuggled into the application using Expat
+ and could cause arbitrary damage there, depending on how
+ malformed UTF-16 was handled inside the application;
+ validation was not their job but Expat's. This is similar
+ to past vulnerability CVE-2022-25235.
+ Upstream CVSS 3.1 vector:
+ AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (CVSS score: 9.8)
+
+ Bug fixes:
+ #1346 lib: Fix OOM-related memory leak on a failed overflow check
+ #1371 lib: Fix memory alignment for architectures with 128bit
+ pointers like CHERI-RISC-V
+
+ Other changes:
+ #1354 lib: Reject an XML declaration version other than `1.[0-9]+`
+ (which is less strict than XML 1.0r4 (fourth edition)
+ and matches XML 1.0r5 (fifth edition))
+ #1357 lib: Drop internal macros FASTCALL, PTRCALL, PTRFASTCALL
+ #1349 Replace some internal use of XML_Bool with standard bool
+ #1360 tests|xmlwf: Add `#include "expat_config.h"` where missing
+ #1378 tests: Fix tail pointer when unlinking the last tracked
+ allocation
+
Mon August 31 2026
Security fixes:
#1321 #1331 CVE-2026-66046, CVE-2026-76641 -- Fix quadratic runtime from
Index: lib/libexpat/lib/internal.h
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/internal.h,v
diff -u -p -r1.17.2.2 internal.h
--- lib/libexpat/lib/internal.h 10 Sep 2026 20:46:02 -0000 1.17.2.2
+++ lib/libexpat/lib/internal.h 2 Oct 2026 22:01:21 -0000
@@ -6,13 +6,6 @@
The following calling convention macros are defined for frequently
called functions:
- FASTCALL - Used for those internal functions that have a simple
- body and a low number of arguments and local variables.
-
- PTRCALL - Used for functions called though function pointers.
-
- PTRFASTCALL - Like PTRCALL, but for low number of arguments.
-
inline - Used for selected internal functions for which inlining
may improve performance on some platforms.
@@ -58,42 +51,6 @@
SPDX-License-Identifier: MIT
*/
-#if defined(__GNUC__) && defined(__i386__) && ! defined(__MINGW32__)
-/* We'll use this version by default only where we know it helps.
-
- regparm() generates warnings on Solaris boxes. See SF bug #692878.
-
- Instability reported with egcs on a RedHat Linux 7.3.
- Let's comment out:
- #define FASTCALL __attribute__((stdcall, regparm(3)))
- and let's try this:
-*/
-# define FASTCALL __attribute__((regparm(3)))
-# define PTRFASTCALL __attribute__((regparm(3)))
-#endif
-
-/* Using __fastcall seems to have an unexpected negative effect under
- MS VC++, especially for function pointers, so we won't use it for
- now on that platform. It may be reconsidered for a future release
- if it can be made more effective.
- Likely reason: __fastcall on Windows is like stdcall, therefore
- the compiler cannot perform stack optimizations for call clusters.
-*/
-
-/* Make sure all of these are defined if they aren't already. */
-
-#ifndef FASTCALL
-# define FASTCALL
-#endif
-
-#ifndef PTRCALL
-# define PTRCALL
-#endif
-
-#ifndef PTRFASTCALL
-# define PTRFASTCALL
-#endif
-
#ifndef XML_MIN_SIZE
# if ! defined(__cplusplus) && ! defined(inline)
# ifdef __GNUC__
@@ -152,7 +109,11 @@
// NOTE: If function expat_alloc was user facing, EXPAT_MALLOC_ALIGNMENT would
// have to take sizeof(long double) into account
-#define EXPAT_MALLOC_ALIGNMENT sizeof(long long) // largest parser (sub)member
+union expat_align {
+ long long l;
+ void *p;
+};
+#define EXPAT_MALLOC_ALIGNMENT sizeof(union expat_align)
#define EXPAT_MALLOC_PADDING ((EXPAT_MALLOC_ALIGNMENT) - sizeof(size_t))
/* NOTE END */
Index: lib/libexpat/lib/xmlparse.c
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmlparse.c,v
diff -u -p -r1.47.2.2 xmlparse.c
--- lib/libexpat/lib/xmlparse.c 10 Sep 2026 20:46:02 -0000 1.47.2.2
+++ lib/libexpat/lib/xmlparse.c 2 Oct 2026 22:01:21 -0000
@@ -310,12 +310,12 @@ typedef struct {
const XML_Char *publicId;
const XML_Char *notation;
bool open;
- XML_Bool hasMore; /* true if entity has not been completely processed */
- /* An entity can be open while being already completely processed (hasMore ==
- XML_FALSE). The reason is the delayed closing of entities until their inner
+ bool hasMore; /* true if entity has not been completely processed */
+ /* An entity can be open while being already completely processed (!hasMore).
+ The reason is the delayed closing of entities until their inner
entities are processed and closed */
- XML_Bool is_param;
- XML_Bool is_internal; /* true if declared in internal subset outside PE */
+ bool is_param;
+ bool is_internal; /* true if declared in internal subset outside PE */
} ENTITY;
typedef struct {
@@ -350,8 +350,8 @@ typedef struct {
typedef struct attribute_id {
XML_Char *name;
PREFIX *prefix;
- XML_Bool maybeTokenized;
- XML_Bool xmlns;
+ bool maybeTokenized;
+ bool xmlns;
} ATTRIBUTE_ID;
typedef struct {
@@ -407,12 +407,12 @@ typedef struct {
XML_Bool standalone;
#ifdef XML_DTD
/* indicates if external PE has been read */
- XML_Bool paramEntityRead;
+ bool paramEntityRead;
HASH_TABLE paramEntities;
#endif /* XML_DTD */
PREFIX defaultPrefix;
/* === scaffolding for building content model === */
- XML_Bool in_eldecl;
+ bool in_eldecl;
CONTENT_SCAFFOLD *scaffold;
unsigned contentStringLen;
unsigned scaffSize;
@@ -434,7 +434,7 @@ typedef struct open_internal_entity {
struct open_internal_entity *next;
ENTITY *entity;
int startTagLevel;
- XML_Bool betweenDecl; /* WFC: PE Between Declarations */
+ bool betweenDecl; /* WFC: PE Between Declarations */
enum EntityType type;
} OPEN_INTERNAL_ENTITY;
@@ -471,8 +471,8 @@ typedef struct entity_stats {
} ENTITY_STATS;
#endif /* XML_GE == 1 */
-typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
- const char *end, const char **endPtr);
+typedef enum XML_Error Processor(XML_Parser parser, const char *start,
+ const char *end, const char **endPtr);
static Processor prologProcessor;
static Processor prologInitProcessor;
@@ -504,7 +504,7 @@ static enum XML_Error doProlog(XML_Parse
XML_Bool haveMore, XML_Bool allowClosingDoctype,
enum XML_Account account);
static enum XML_Error processEntity(XML_Parser parser, ENTITY *entity,
- XML_Bool betweenDecl, enum EntityType type);
+ bool betweenDecl, enum EntityType type);
static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
const ENCODING *enc, const char *start,
const char *end, const char **endPtr,
@@ -564,7 +564,7 @@ static void reportDefault(XML_Parser par
static const XML_Char *getContext(XML_Parser parser);
static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
-static void FASTCALL normalizePublicId(XML_Char *s);
+static void normalizePublicId(XML_Char *s);
static DTD *dtdCreate(XML_Parser parser);
/* do not call if m_parentParser != NULL */
@@ -578,32 +578,29 @@ static NAMED *lookupWithLength(XML_Parse
size_t nameLen, size_t createSize);
static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
size_t createSize);
-static void FASTCALL hashTableInit(HASH_TABLE *table, XML_Parser parser);
-static void FASTCALL hashTableClear(HASH_TABLE *table);
-static void FASTCALL hashTableDestroy(HASH_TABLE *table);
-static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter,
- const HASH_TABLE *table);
-static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter);
-
-static void FASTCALL poolInit(STRING_POOL *pool, XML_Parser parser);
-static void FASTCALL poolClear(STRING_POOL *pool);
-static void FASTCALL poolDestroy(STRING_POOL *pool);
+static void hashTableInit(HASH_TABLE *table, XML_Parser parser);
+static void hashTableClear(HASH_TABLE *table);
+static void hashTableDestroy(HASH_TABLE *table);
+static void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table);
+static NAMED *hashTableIterNext(HASH_TABLE_ITER *iter);
+
+static void poolInit(STRING_POOL *pool, XML_Parser parser);
+static void poolClear(STRING_POOL *pool);
+static void poolDestroy(STRING_POOL *pool);
static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end);
static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
const char *ptr, const char *end);
-static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
-static bool FASTCALL poolGrowUntil(STRING_POOL *pool, size_t needed);
-static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
- const XML_Char *s);
-static const XML_Char *FASTCALL poolCopyStringNoFinish(STRING_POOL *pool,
- const XML_Char *s);
+static XML_Bool poolGrow(STRING_POOL *pool);
+static bool poolGrowUntil(STRING_POOL *pool, size_t needed);
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *poolCopyStringNoFinish(STRING_POOL *pool,
+ const XML_Char *s);
static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
int n);
-static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
- const XML_Char *s);
+static const XML_Char *poolAppendString(STRING_POOL *pool, const XML_Char *s);
-static int FASTCALL nextScaffoldPart(XML_Parser parser);
+static int nextScaffoldPart(XML_Parser parser);
static XML_Content *build_model(XML_Parser parser);
static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
const char *ptr, const char *end);
@@ -1572,7 +1569,7 @@ parserInit(XML_Parser parser, const XML_
}
/* moves list of bindings to m_freeBindingList */
-static void FASTCALL
+static void
moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {
while (bindings) {
BINDING *b = bindings;
@@ -1845,7 +1842,7 @@ XML_ExternalEntityParserCreate(XML_Parse
return parser;
}
-static void FASTCALL
+static void
destroyBindings(BINDING *bindings, XML_Parser parser) {
for (;;) {
BINDING *b = bindings;
@@ -3119,7 +3116,7 @@ storeRawNames(XML_Parser parser) {
return XML_TRUE;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
contentProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
enum XML_Error result = doContent(
@@ -3133,7 +3130,7 @@ contentProcessor(XML_Parser parser, cons
return result;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalEntityInitProcessor(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
enum XML_Error result = initializeEncoding(parser);
@@ -3143,7 +3140,7 @@ externalEntityInitProcessor(XML_Parser p
return externalEntityInitProcessor2(parser, start, end, endPtr);
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalEntityInitProcessor2(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
const char *next = start; /* XmlContentTok doesn't always set the last arg */
@@ -3188,7 +3185,7 @@ externalEntityInitProcessor2(XML_Parser
return externalEntityInitProcessor3(parser, start, end, endPtr);
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalEntityInitProcessor3(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
int tok;
@@ -3240,7 +3237,7 @@ externalEntityInitProcessor3(XML_Parser
return externalEntityContentProcessor(parser, start, end, endPtr);
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalEntityContentProcessor(XML_Parser parser, const char *start,
const char *end, const char **endPtr) {
enum XML_Error result
@@ -4502,6 +4499,7 @@ addBinding(XML_Parser parser, PREFIX *pr
/* Detect and prevent integer overflow */
if (len > SIZE_MAX - EXPAND_SPARE
|| len + EXPAND_SPARE > SIZE_MAX / sizeof(XML_Char)) {
+ FREE(parser, b);
return XML_ERROR_NO_MEMORY;
}
@@ -4539,7 +4537,7 @@ addBinding(XML_Parser parser, PREFIX *pr
/* The idea here is to avoid using stack for each CDATA section when
the whole file is parsed with one call.
*/
-static enum XML_Error PTRCALL
+static enum XML_Error
cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
enum XML_Error result = doCdataSection(
@@ -4705,7 +4703,7 @@ doCdataSection(XML_Parser parser, const
/* The idea here is to avoid using stack for each IGNORE section when
the whole file is parsed with one call.
*/
-static enum XML_Error PTRCALL
+static enum XML_Error
ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
enum XML_Error result
@@ -4975,7 +4973,7 @@ handleUnknownEncoding(XML_Parser parser,
return XML_ERROR_UNKNOWN_ENCODING;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
prologInitProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
enum XML_Error result = initializeEncoding(parser);
@@ -4987,7 +4985,7 @@ prologInitProcessor(XML_Parser parser, c
#ifdef XML_DTD
-static enum XML_Error PTRCALL
+static enum XML_Error
externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
enum XML_Error result = initializeEncoding(parser);
@@ -4996,7 +4994,7 @@ externalParEntInitProcessor(XML_Parser p
/* we know now that XML_Parse(Buffer) has been called,
so we consider the external parameter entity read */
- parser->m_dtd->paramEntityRead = XML_TRUE;
+ parser->m_dtd->paramEntityRead = true;
if (parser->m_prologState.inEntityValue) {
parser->m_processor = entityValueInitProcessor;
@@ -5007,7 +5005,7 @@ externalParEntInitProcessor(XML_Parser p
}
}
-static enum XML_Error PTRCALL
+static enum XML_Error
entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
int tok;
@@ -5091,7 +5089,7 @@ entityValueInitProcessor(XML_Parser pars
}
}
-static enum XML_Error PTRCALL
+static enum XML_Error
externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
const char *next = s;
@@ -5137,7 +5135,7 @@ externalParEntProcessor(XML_Parser parse
XML_ACCOUNT_DIRECT);
}
-static enum XML_Error PTRCALL
+static enum XML_Error
entityValueProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
const char *start = s;
@@ -5184,7 +5182,7 @@ entityValueProcessor(XML_Parser parser,
#endif /* XML_DTD */
-static enum XML_Error PTRCALL
+static enum XML_Error
prologProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
const char *next = s;
@@ -5430,7 +5428,7 @@ doProlog(XML_Parser parser, const ENCODI
}
if (parser->m_useForeignDTD)
entity->base = parser->m_curBase;
- dtd->paramEntityRead = XML_FALSE;
+ dtd->paramEntityRead = false;
beforeHandler(parser);
const int status = parser->m_externalEntityRefHandler(
parser->m_externalEntityRefHandlerArg, 0, entity->base,
@@ -5480,7 +5478,7 @@ doProlog(XML_Parser parser, const ENCODI
if (! entity)
return XML_ERROR_NO_MEMORY;
entity->base = parser->m_curBase;
- dtd->paramEntityRead = XML_FALSE;
+ dtd->paramEntityRead = false;
beforeHandler(parser);
const int status = parser->m_externalEntityRefHandler(
parser->m_externalEntityRefHandlerArg, 0, entity->base,
@@ -5823,7 +5821,7 @@ doProlog(XML_Parser parser, const ENCODI
} else {
poolFinish(&dtd->pool);
parser->m_declEntity->publicId = NULL;
- parser->m_declEntity->is_param = XML_FALSE;
+ parser->m_declEntity->is_param = false;
/* if we have a parent parser or are reading an internal parameter
entity, then the entity declaration is not considered "internal"
*/
@@ -5853,7 +5851,7 @@ doProlog(XML_Parser parser, const ENCODI
} else {
poolFinish(&dtd->pool);
parser->m_declEntity->publicId = NULL;
- parser->m_declEntity->is_param = XML_TRUE;
+ parser->m_declEntity->is_param = true;
/* if we have a parent parser or are reading an internal parameter
entity, then the entity declaration is not considered "internal"
*/
@@ -6088,8 +6086,7 @@ doProlog(XML_Parser parser, const ENCODI
return XML_ERROR_RECURSIVE_ENTITY_REF;
if (entity->textPtr) {
enum XML_Error result;
- XML_Bool betweenDecl
- = (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
+ bool betweenDecl = (role == XML_ROLE_PARAM_ENTITY_REF);
result = processEntity(parser, entity, betweenDecl, ENTITY_INTERNAL);
if (result != XML_ERROR_NONE)
return result;
@@ -6097,7 +6094,7 @@ doProlog(XML_Parser parser, const ENCODI
break;
}
if (parser->m_externalEntityRefHandler) {
- dtd->paramEntityRead = XML_FALSE;
+ dtd->paramEntityRead = false;
entity->open = true;
entityTrackingOnOpen(parser, entity, __LINE__);
beforeHandler(parser);
@@ -6141,7 +6138,7 @@ doProlog(XML_Parser parser, const ENCODI
return XML_ERROR_NO_MEMORY;
dtd->scaffLevel = 0;
dtd->scaffCount = 0;
- dtd->in_eldecl = XML_TRUE;
+ dtd->in_eldecl = true;
handleDefault = XML_FALSE;
}
break;
@@ -6170,7 +6167,7 @@ doProlog(XML_Parser parser, const ENCODI
afterHandler(parser);
handleDefault = XML_FALSE;
}
- dtd->in_eldecl = XML_FALSE;
+ dtd->in_eldecl = false;
}
break;
@@ -6252,7 +6249,7 @@ doProlog(XML_Parser parser, const ENCODI
parser->m_handlerArg, parser->m_declElementType->name, model);
afterHandler(parser);
}
- dtd->in_eldecl = XML_FALSE;
+ dtd->in_eldecl = false;
dtd->contentStringLen = 0;
}
}
@@ -6321,7 +6318,7 @@ doProlog(XML_Parser parser, const ENCODI
/* not reached */
}
-static enum XML_Error PTRCALL
+static enum XML_Error
epilogProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
parser->m_processor = epilogProcessor;
@@ -6400,7 +6397,7 @@ epilogProcessor(XML_Parser parser, const
}
static enum XML_Error
-processEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl,
+processEntity(XML_Parser parser, ENTITY *entity, bool betweenDecl,
enum EntityType type) {
OPEN_INTERNAL_ENTITY *openEntity, **openEntityList;
OPEN_INTERNAL_ENTITY **const freeEntityList = &parser->m_freeEntities;
@@ -6436,7 +6433,7 @@ processEntity(XML_Parser parser, ENTITY
return XML_ERROR_NO_MEMORY;
}
entity->open = true;
- entity->hasMore = XML_TRUE;
+ entity->hasMore = true;
#if XML_GE == 1
entityTrackingOnOpen(parser, entity, __LINE__);
#endif
@@ -6458,7 +6455,7 @@ processEntity(XML_Parser parser, ENTITY
return XML_ERROR_NONE;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
UNUSED_P(s);
@@ -6508,7 +6505,7 @@ internalEntityProcessor(XML_Parser parse
// Entity is complete. We cannot close it here since we need to first
// process its possible inner entities (which are added to the
// m_openInternalEntities during doProlog or doContent calls above)
- entity->hasMore = XML_FALSE;
+ entity->hasMore = false;
if (! entity->is_param
&& (openEntity->startTagLevel != parser->m_tagLevel)) {
return XML_ERROR_ASYNC_ENTITY;
@@ -6540,7 +6537,7 @@ internalEntityProcessor(XML_Parser parse
return XML_ERROR_NONE;
}
-static enum XML_Error PTRCALL
+static enum XML_Error
errorProcessor(XML_Parser parser, const char *s, const char *end,
const char **nextPtr) {
UNUSED_P(s);
@@ -6591,7 +6588,7 @@ storeAttributeValue(XML_Parser parser, c
// Entity is complete. We cannot close it here since we need to first
// process its possible inner entities (which are added to the
// m_openAttributeEntities during appendAttributeValue)
- entity->hasMore = XML_FALSE;
+ entity->hasMore = false;
continue;
} // End of entity processing, "if" block skips the rest
@@ -6899,7 +6896,7 @@ storeEntityValue(XML_Parser parser, cons
}
if (entity->systemId) {
if (parser->m_externalEntityRefHandler) {
- dtd->paramEntityRead = XML_FALSE;
+ dtd->paramEntityRead = false;
entity->open = true;
entityTrackingOnOpen(parser, entity, __LINE__);
beforeHandler(parser);
@@ -7051,7 +7048,7 @@ callStoreEntityValue(XML_Parser parser,
// Entity is complete. We cannot close it here since we need to first
// process its possible inner entities (which are added to the
// m_openValueEntities during storeEntityValue)
- entity->hasMore = XML_FALSE;
+ entity->hasMore = false;
continue;
} // End of entity processing, "if" block skips the rest
@@ -7113,7 +7110,7 @@ storeSelfEntityValue(XML_Parser parser,
#endif /* XML_GE == 0 */
-static void FASTCALL
+static void
normalizeLines(XML_Char *s) {
XML_Char *p;
for (;; s++) {
@@ -7279,7 +7276,7 @@ defineAttribute(ELEMENT_TYPE *type, ATTR
att->value = value;
att->isCdata = isCdata;
if (! isCdata)
- attId->maybeTokenized = XML_TRUE;
+ attId->maybeTokenized = true;
NAME_AND_DEFAULT_ATTRIBUTE *const nameAndDefaultAttribute
= (NAME_AND_DEFAULT_ATTRIBUTE *)lookup(
@@ -7364,7 +7361,7 @@ getAttributeId(XML_Parser parser, const
else
id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6,
sizeof(PREFIX));
- id->xmlns = XML_TRUE;
+ id->xmlns = true;
} else {
int i;
for (i = 0; name[i]; i++) {
@@ -7554,7 +7551,7 @@ setContext(XML_Parser parser, const XML_
return XML_TRUE;
}
-static void FASTCALL
+static void
normalizePublicId(XML_Char *publicId) {
XML_Char *p = publicId;
XML_Char *s;
@@ -7587,13 +7584,13 @@ dtdCreate(XML_Parser parser) {
hashTableInit(&(p->attributeIds), parser);
hashTableInit(&(p->prefixes), parser);
#ifdef XML_DTD
- p->paramEntityRead = XML_FALSE;
+ p->paramEntityRead = false;
hashTableInit(&(p->paramEntities), parser);
#endif /* XML_DTD */
p->defaultPrefix.name = NULL;
p->defaultPrefix.binding = NULL;
- p->in_eldecl = XML_FALSE;
+ p->in_eldecl = false;
p->scaffIndex = NULL;
p->scaffIndexSize = 0;
p->scaffold = NULL;
@@ -7621,7 +7618,7 @@ dtdReset(DTD *p, XML_Parser parser) {
}
hashTableClear(&(p->generalEntities));
#ifdef XML_DTD
- p->paramEntityRead = XML_FALSE;
+ p->paramEntityRead = false;
hashTableClear(&(p->paramEntities));
#endif /* XML_DTD */
hashTableClear(&(p->elementTypes));
@@ -7632,7 +7629,7 @@ dtdReset(DTD *p, XML_Parser parser) {
p->defaultPrefix.name = NULL;
p->defaultPrefix.binding = NULL;
- p->in_eldecl = XML_FALSE;
+ p->in_eldecl = false;
FREE(parser, p->scaffIndex);
p->scaffIndex = NULL;
@@ -7900,7 +7897,7 @@ copyEntityTable(XML_Parser oldParser, HA
// Compares two strings `s1` and `s2` whereas:
// - `s2` is zero-terminated but
// - `s1` is made up of exactly (not just up to) `s1len` non-zero characters.
-static XML_Bool FASTCALL
+static XML_Bool
keyeq(KEY s1, size_t s1len, KEY s2) {
#ifdef XML_UNICODE
# ifdef XML_UNICODE_WCHAR_T
@@ -7930,7 +7927,7 @@ copy_salt_to_sipkey(XML_Parser parser, s
*key = rootParser->m_hash_secret_salt_128;
}
-static unsigned long FASTCALL
+static unsigned long
hash(XML_Parser parser, KEY s, size_t keyLen) {
struct siphash state;
struct sipkey key;
@@ -8072,7 +8069,7 @@ lookup(XML_Parser parser, HASH_TABLE *ta
return lookupWithLength(parser, table, name, keylen(name), createSize);
}
-static void FASTCALL
+static void
hashTableClear(HASH_TABLE *table) {
size_t i;
for (i = 0; i < table->size; i++) {
@@ -8082,7 +8079,7 @@ hashTableClear(HASH_TABLE *table) {
table->used = 0;
}
-static void FASTCALL
+static void
hashTableDestroy(HASH_TABLE *table) {
size_t i;
for (i = 0; i < table->size; i++)
@@ -8090,7 +8087,7 @@ hashTableDestroy(HASH_TABLE *table) {
FREE(table->parser, table->v);
}
-static void FASTCALL
+static void
hashTableInit(HASH_TABLE *p, XML_Parser parser) {
p->power = 0;
p->size = 0;
@@ -8099,13 +8096,13 @@ hashTableInit(HASH_TABLE *p, XML_Parser
p->parser = parser;
}
-static void FASTCALL
+static void
hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
iter->p = table->v;
iter->end = iter->p ? iter->p + table->size : NULL;
}
-static NAMED *FASTCALL
+static NAMED *
hashTableIterNext(HASH_TABLE_ITER *iter) {
while (iter->p != iter->end) {
NAMED *tem = *(iter->p)++;
@@ -8115,7 +8112,7 @@ hashTableIterNext(HASH_TABLE_ITER *iter)
return NULL;
}
-static void FASTCALL
+static void
poolInit(STRING_POOL *pool, XML_Parser parser) {
pool->blocks = NULL;
pool->freeBlocks = NULL;
@@ -8125,7 +8122,7 @@ poolInit(STRING_POOL *pool, XML_Parser p
pool->parser = parser;
}
-static void FASTCALL
+static void
poolClear(STRING_POOL *pool) {
if (! pool->freeBlocks)
pool->freeBlocks = pool->blocks;
@@ -8144,7 +8141,7 @@ poolClear(STRING_POOL *pool) {
pool->end = NULL;
}
-static void FASTCALL
+static void
poolDestroy(STRING_POOL *pool) {
BLOCK *p = pool->blocks;
while (p) {
@@ -8177,7 +8174,7 @@ poolAppend(STRING_POOL *pool, const ENCO
return pool->start;
}
-static const XML_Char *FASTCALL
+static const XML_Char *
poolCopyString(STRING_POOL *pool, const XML_Char *s) {
if (! poolAppendChars(pool, s, xcslen(s) + /*null terminator*/ 1))
return NULL;
@@ -8188,7 +8185,7 @@ poolCopyString(STRING_POOL *pool, const
// A version of `poolCopyString` that does not call `poolFinish`
// and reverts any partial advancement upon failure.
-static const XML_Char *FASTCALL
+static const XML_Char *
poolCopyStringNoFinish(STRING_POOL *pool, const XML_Char *s) {
const XML_Char *const original = s;
do {
@@ -8226,7 +8223,7 @@ poolCopyStringN(STRING_POOL *pool, const
return s;
}
-static const XML_Char *FASTCALL
+static const XML_Char *
poolAppendString(STRING_POOL *pool, const XML_Char *s) {
if (! poolAppendChars(pool, s, xcslen(s)))
return NULL;
@@ -8271,7 +8268,7 @@ poolBytesToAllocateFor(int blockSize) {
}
}
-static XML_Bool FASTCALL
+static XML_Bool
poolGrow(STRING_POOL *pool) {
if (pool->freeBlocks) {
if (pool->start == NULL) {
@@ -8376,7 +8373,7 @@ poolGrow(STRING_POOL *pool) {
return XML_TRUE;
}
-static bool FASTCALL
+static bool
poolGrowUntil(STRING_POOL *pool, size_t needed) {
for (;;) {
const size_t available = pool->end - pool->ptr;
@@ -8389,7 +8386,7 @@ poolGrowUntil(STRING_POOL *pool, size_t
}
}
-static int FASTCALL
+static int
nextScaffoldPart(XML_Parser parser) {
DTD *const dtd = parser->m_dtd; /* save one level of indirection */
CONTENT_SCAFFOLD *me;
Index: lib/libexpat/lib/xmlrole.c
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmlrole.c,v
diff -u -p -r1.15.4.1 xmlrole.c
--- lib/libexpat/lib/xmlrole.c 20 Aug 2026 07:49:22 -0000 1.15.4.1
+++ lib/libexpat/lib/xmlrole.c 2 Oct 2026 22:01:22 -0000
@@ -121,9 +121,8 @@ static const char KW_SYSTEM[]
# define setTopLevel(state) ((state)->handler = internalSubset)
#endif /* not XML_DTD */
-typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state, int tok,
- const char *ptr, const char *end,
- const ENCODING *enc);
+typedef int PROLOG_HANDLER(PROLOG_STATE *state, int tok, const char *ptr,
+ const char *end, const ENCODING *enc);
static PROLOG_HANDLER prolog0, prolog1, prolog2, doctype0, doctype1, doctype2,
doctype3, doctype4, doctype5, internalSubset, entity0, entity1, entity2,
@@ -137,9 +136,9 @@ static PROLOG_HANDLER prolog0, prolog1,
#endif /* XML_DTD */
declClose, error;
-static int FASTCALL common(PROLOG_STATE *state, int tok);
+static int common(PROLOG_STATE *state, int tok);
-static int PTRCALL
+static int
prolog0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -170,7 +169,7 @@ prolog0(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
prolog1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -202,7 +201,7 @@ prolog1(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
prolog2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -222,7 +221,7 @@ prolog2(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
doctype0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -239,7 +238,7 @@ doctype0(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
doctype1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -265,7 +264,7 @@ doctype1(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
doctype2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -281,7 +280,7 @@ doctype2(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
doctype3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -297,7 +296,7 @@ doctype3(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
doctype4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -316,7 +315,7 @@ doctype4(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
doctype5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -332,7 +331,7 @@ doctype5(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
internalSubset(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -377,7 +376,7 @@ internalSubset(PROLOG_STATE *state, int
#ifdef XML_DTD
-static int PTRCALL
+static int
externalSubset0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
state->handler = externalSubset1;
@@ -386,7 +385,7 @@ externalSubset0(PROLOG_STATE *state, int
return externalSubset1(state, tok, ptr, end, enc);
}
-static int PTRCALL
+static int
externalSubset1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -414,7 +413,7 @@ externalSubset1(PROLOG_STATE *state, int
#endif /* XML_DTD */
-static int PTRCALL
+static int
entity0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -433,7 +432,7 @@ entity0(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -449,7 +448,7 @@ entity1(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -473,7 +472,7 @@ entity2(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -489,7 +488,7 @@ entity3(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -505,7 +504,7 @@ entity4(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -524,7 +523,7 @@ entity5(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -541,7 +540,7 @@ entity6(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -565,7 +564,7 @@ entity7(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity8(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -581,7 +580,7 @@ entity8(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity9(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -597,7 +596,7 @@ entity9(PROLOG_STATE *state, int tok, co
return common(state, tok);
}
-static int PTRCALL
+static int
entity10(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -613,7 +612,7 @@ entity10(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
notation0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -629,7 +628,7 @@ notation0(PROLOG_STATE *state, int tok,
return common(state, tok);
}
-static int PTRCALL
+static int
notation1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -649,7 +648,7 @@ notation1(PROLOG_STATE *state, int tok,
return common(state, tok);
}
-static int PTRCALL
+static int
notation2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -665,7 +664,7 @@ notation2(PROLOG_STATE *state, int tok,
return common(state, tok);
}
-static int PTRCALL
+static int
notation3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -682,7 +681,7 @@ notation3(PROLOG_STATE *state, int tok,
return common(state, tok);
}
-static int PTRCALL
+static int
notation4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -702,7 +701,7 @@ notation4(PROLOG_STATE *state, int tok,
return common(state, tok);
}
-static int PTRCALL
+static int
attlist0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -719,7 +718,7 @@ attlist0(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
attlist1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -739,7 +738,7 @@ attlist1(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
attlist2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -769,7 +768,7 @@ attlist2(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
attlist3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -787,7 +786,7 @@ attlist3(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
attlist4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -806,7 +805,7 @@ attlist4(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
attlist5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -822,7 +821,7 @@ attlist5(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
attlist6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -838,7 +837,7 @@ attlist6(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
attlist7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -858,7 +857,7 @@ attlist7(PROLOG_STATE *state, int tok, c
}
/* default value */
-static int PTRCALL
+static int
attlist8(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -888,7 +887,7 @@ attlist8(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
attlist9(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -904,7 +903,7 @@ attlist9(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
element0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -921,7 +920,7 @@ element0(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
element1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -947,7 +946,7 @@ element1(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
element2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -981,7 +980,7 @@ element2(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
element3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1005,7 +1004,7 @@ element3(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
element4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1022,7 +1021,7 @@ element4(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
element5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1042,7 +1041,7 @@ element5(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
element6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1071,7 +1070,7 @@ element6(PROLOG_STATE *state, int tok, c
return common(state, tok);
}
-static int PTRCALL
+static int
element7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1120,7 +1119,7 @@ element7(PROLOG_STATE *state, int tok, c
#ifdef XML_DTD
-static int PTRCALL
+static int
condSect0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
switch (tok) {
@@ -1140,7 +1139,7 @@ condSect0(PROLOG_STATE *state, int tok,
return common(state, tok);
}
-static int PTRCALL
+static int
condSect1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1157,7 +1156,7 @@ condSect1(PROLOG_STATE *state, int tok,
return common(state, tok);
}
-static int PTRCALL
+static int
condSect2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1175,7 +1174,7 @@ condSect2(PROLOG_STATE *state, int tok,
#endif /* XML_DTD */
-static int PTRCALL
+static int
declClose(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(ptr);
@@ -1211,7 +1210,7 @@ declClose(PROLOG_STATE *state, int tok,
*
* LCOV_EXCL_START
*/
-static int PTRCALL
+static int
error(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
const ENCODING *enc) {
UNUSED_P(state);
@@ -1223,7 +1222,7 @@ error(PROLOG_STATE *state, int tok, cons
}
/* LCOV_EXCL_STOP */
-static int FASTCALL
+static int
common(PROLOG_STATE *state, int tok) {
#ifdef XML_DTD
if (! state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
Index: lib/libexpat/lib/xmlrole.h
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmlrole.h,v
diff -u -p -r1.7.6.1 xmlrole.h
--- lib/libexpat/lib/xmlrole.h 20 Aug 2026 07:49:22 -0000 1.7.6.1
+++ lib/libexpat/lib/xmlrole.h 2 Oct 2026 22:01:22 -0000
@@ -112,8 +112,8 @@ enum {
};
typedef struct prolog_state {
- int(PTRCALL *handler)(struct prolog_state *state, int tok, const char *ptr,
- const char *end, const ENCODING *enc);
+ int (*handler)(struct prolog_state *state, int tok, const char *ptr,
+ const char *end, const ENCODING *enc);
unsigned level;
int role_none;
# ifdef XML_DTD
Index: lib/libexpat/lib/xmltok.c
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmltok.c,v
diff -u -p -r1.20.4.1 xmltok.c
--- lib/libexpat/lib/xmltok.c 20 Aug 2026 07:49:22 -0000 1.20.4.1
+++ lib/libexpat/lib/xmltok.c 2 Oct 2026 22:01:22 -0000
@@ -136,20 +136,20 @@
: ((p)[1] & 0x80) == 0 \
|| ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
-static int PTRFASTCALL
+static int
isNever(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
UNUSED_P(p);
return 0;
}
-static int PTRFASTCALL
+static int
utf8_isName2(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
}
-static int PTRFASTCALL
+static int
utf8_isName3(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
@@ -157,13 +157,13 @@ utf8_isName3(const ENCODING *enc, const
#define utf8_isName4 isNever
-static int PTRFASTCALL
+static int
utf8_isNmstrt2(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
}
-static int PTRFASTCALL
+static int
utf8_isNmstrt3(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
@@ -171,19 +171,19 @@ utf8_isNmstrt3(const ENCODING *enc, cons
#define utf8_isNmstrt4 isNever
-static int PTRFASTCALL
+static int
utf8_isInvalid2(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_INVALID2((const unsigned char *)p);
}
-static int PTRFASTCALL
+static int
utf8_isInvalid3(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_INVALID3((const unsigned char *)p);
}
-static int PTRFASTCALL
+static int
utf8_isInvalid4(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return UTF8_INVALID4((const unsigned char *)p);
@@ -193,21 +193,21 @@ struct normal_encoding {
ENCODING enc;
unsigned char type[256];
#ifdef XML_MIN_SIZE
- int(PTRFASTCALL *byteType)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNameMin)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *);
- int(PTRFASTCALL *byteToAscii)(const ENCODING *, const char *);
- int(PTRCALL *charMatches)(const ENCODING *, const char *, int);
+ int (*byteType)(const ENCODING *, const char *);
+ int (*isNameMin)(const ENCODING *, const char *);
+ int (*isNmstrtMin)(const ENCODING *, const char *);
+ int (*byteToAscii)(const ENCODING *, const char *);
+ int (*charMatches)(const ENCODING *, const char *, int);
#endif /* XML_MIN_SIZE */
- int(PTRFASTCALL *isName2)(const ENCODING *, const char *);
- int(PTRFASTCALL *isName3)(const ENCODING *, const char *);
- int(PTRFASTCALL *isName4)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *);
- int(PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *);
- int(PTRFASTCALL *isInvalid2)(const ENCODING *, const char *);
- int(PTRFASTCALL *isInvalid3)(const ENCODING *, const char *);
- int(PTRFASTCALL *isInvalid4)(const ENCODING *, const char *);
+ int (*isName2)(const ENCODING *, const char *);
+ int (*isName3)(const ENCODING *, const char *);
+ int (*isName4)(const ENCODING *, const char *);
+ int (*isNmstrt2)(const ENCODING *, const char *);
+ int (*isNmstrt3)(const ENCODING *, const char *);
+ int (*isNmstrt4)(const ENCODING *, const char *);
+ int (*isInvalid2)(const ENCODING *, const char *);
+ int (*isInvalid3)(const ENCODING *, const char *);
+ int (*isInvalid4)(const ENCODING *, const char *);
};
#define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *)(enc))
@@ -232,7 +232,20 @@ struct normal_encoding {
/* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL, \
/* isInvalid2 */ NULL, /* isInvalid3 */ NULL, /* isInvalid4 */ NULL
-static int FASTCALL checkCharRefNumber(int result);
+/* Like NULL_VTABLE but with a real isInvalid4 so the UTF-16 encodings reject a
+ high surrogate that is not followed by a low surrogate. Only needed for the
+ XML_MIN_SIZE build, where the shared tokenizer dispatches through the vtable;
+ the regular build inlines the same check via IS_INVALID_CHAR. */
+#ifdef XML_MIN_SIZE
+# define UTF16_NULL_VTABLE(E) \
+ /* isName2 */ NULL, /* isName3 */ NULL, /* isName4 */ NULL, \
+ /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL, \
+ /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, E##isInvalid4
+#else
+# define UTF16_NULL_VTABLE(E) NULL_VTABLE
+#endif
+
+static int checkCharRefNumber(int result);
#include "xmltok_impl.h"
#include "ascii.h"
@@ -253,7 +266,7 @@ static int FASTCALL checkCharRefNumber(i
(((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
#ifdef XML_MIN_SIZE
-static int PTRFASTCALL
+static int
sb_byteType(const ENCODING *enc, const char *p) {
return SB_BYTE_TYPE(enc, p);
}
@@ -264,7 +277,7 @@ sb_byteType(const ENCODING *enc, const c
#ifdef XML_MIN_SIZE
# define BYTE_TO_ASCII(enc, p) (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
-static int PTRFASTCALL
+static int
sb_byteToAscii(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return *p;
@@ -297,7 +310,7 @@ sb_byteToAscii(const ENCODING *enc, cons
#ifdef XML_MIN_SIZE
# define CHAR_MATCHES(enc, p, c) \
(AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
-static int PTRCALL
+static int
sb_charMatches(const ENCODING *enc, const char *p, int c) {
UNUSED_P(enc);
return *p == c;
@@ -368,7 +381,7 @@ _INTERNAL_trim_to_complete_utf8_characte
*fromLimRef = fromLim;
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
char **toP, const char *toLim) {
bool input_incomplete = false;
@@ -407,7 +420,7 @@ utf8_toUtf8(const ENCODING *enc, const c
return XML_CONVERT_COMPLETED;
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
unsigned short **toP, const unsigned short *toLim) {
enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
@@ -505,7 +518,7 @@ static const struct normal_encoding inte
},
STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
char **toP, const char *toLim) {
UNUSED_P(enc);
@@ -528,7 +541,7 @@ latin1_toUtf8(const ENCODING *enc, const
}
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
unsigned short **toP, const unsigned short *toLim) {
UNUSED_P(enc);
@@ -563,7 +576,7 @@ static const struct normal_encoding lati
},
STANDARD_VTABLE(sb_) NULL_VTABLE};
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
char **toP, const char *toLim) {
UNUSED_P(enc);
@@ -598,7 +611,7 @@ static const struct normal_encoding asci
},
STANDARD_VTABLE(sb_) NULL_VTABLE};
-static int PTRFASTCALL
+static int
unicode_byte_type(char hi, char lo) {
switch ((unsigned char)hi) {
/* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */
@@ -625,7 +638,7 @@ unicode_byte_type(char hi, char lo) {
}
#define DEFINE_UTF16_TO_UTF8(E) \
- static enum XML_Convert_Result PTRCALL E##toUtf8( \
+ static enum XML_Convert_Result E##toUtf8( \
const ENCODING *enc, const char **fromP, const char *fromLim, \
char **toP, const char *toLim) { \
const char *from = *fromP; \
@@ -702,7 +715,7 @@ unicode_byte_type(char hi, char lo) {
}
#define DEFINE_UTF16_TO_UTF16(E) \
- static enum XML_Convert_Result PTRCALL E##toUtf16( \
+ static enum XML_Convert_Result E##toUtf16( \
const ENCODING *enc, const char **fromP, const char *fromLim, \
unsigned short **toP, const unsigned short *toLim) { \
enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
@@ -749,38 +762,49 @@ DEFINE_UTF16_TO_UTF16(big2_)
UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) \
UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+/* A 4-byte UTF-16 character is a surrogate pair; byteType only reports BT_LEAD4
+ for a high surrogate, so the pair is invalid unless the second unit is a low
+ surrogate (U+DC00..U+DFFF, i.e. high byte 0xDC..0xDF). */
+#define LITTLE2_IS_INVALID_CHAR(p, n) \
+ ((n) == 4 && ((unsigned char)(p)[3] & 0xFC) != 0xDC)
#ifdef XML_MIN_SIZE
-static int PTRFASTCALL
+static int
little2_byteType(const ENCODING *enc, const char *p) {
return LITTLE2_BYTE_TYPE(enc, p);
}
-static int PTRFASTCALL
+static int
little2_byteToAscii(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return LITTLE2_BYTE_TO_ASCII(p);
}
-static int PTRCALL
+static int
little2_charMatches(const ENCODING *enc, const char *p, int c) {
UNUSED_P(enc);
return LITTLE2_CHAR_MATCHES(p, c);
}
-static int PTRFASTCALL
+static int
little2_isNameMin(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return LITTLE2_IS_NAME_CHAR_MINBPC(p);
}
-static int PTRFASTCALL
+static int
little2_isNmstrtMin(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return LITTLE2_IS_NMSTRT_CHAR_MINBPC(p);
}
+static int
+little2_isInvalid4(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ return LITTLE2_IS_INVALID_CHAR(p, 4);
+}
+
# undef VTABLE
# define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
@@ -797,6 +821,7 @@ little2_isNmstrtMin(const ENCODING *enc,
# define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
# define IS_NMSTRT_CHAR(enc, p, n) (0)
# define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)
+# define IS_INVALID_CHAR(enc, p, n) LITTLE2_IS_INVALID_CHAR(p, n)
# define XML_TOK_IMPL_C
# include "xmltok_impl.c"
@@ -828,7 +853,7 @@ static const struct normal_encoding litt
# include "asciitab.h"
# include "latin1tab.h"
},
- STANDARD_VTABLE(little2_) NULL_VTABLE};
+ STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
#endif
@@ -846,7 +871,7 @@ static const struct normal_encoding litt
#undef BT_COLON
#include "latin1tab.h"
},
- STANDARD_VTABLE(little2_) NULL_VTABLE};
+ STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
#if BYTEORDER != 4321
@@ -858,7 +883,7 @@ static const struct normal_encoding inte
# include "iasciitab.h"
# include "latin1tab.h"
},
- STANDARD_VTABLE(little2_) NULL_VTABLE};
+ STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
# endif
@@ -870,7 +895,7 @@ static const struct normal_encoding inte
# undef BT_COLON
# include "latin1tab.h"
},
- STANDARD_VTABLE(little2_) NULL_VTABLE};
+ STANDARD_VTABLE(little2_) UTF16_NULL_VTABLE(little2_)};
#endif
@@ -882,38 +907,49 @@ static const struct normal_encoding inte
UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
#define BIG2_IS_NMSTRT_CHAR_MINBPC(p) \
UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+/* A 4-byte UTF-16 character is a surrogate pair; byteType only reports BT_LEAD4
+ for a high surrogate, so the pair is invalid unless the second unit is a low
+ surrogate (U+DC00..U+DFFF, i.e. high byte 0xDC..0xDF). */
+#define BIG2_IS_INVALID_CHAR(p, n) \
+ ((n) == 4 && ((unsigned char)(p)[2] & 0xFC) != 0xDC)
#ifdef XML_MIN_SIZE
-static int PTRFASTCALL
+static int
big2_byteType(const ENCODING *enc, const char *p) {
return BIG2_BYTE_TYPE(enc, p);
}
-static int PTRFASTCALL
+static int
big2_byteToAscii(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return BIG2_BYTE_TO_ASCII(p);
}
-static int PTRCALL
+static int
big2_charMatches(const ENCODING *enc, const char *p, int c) {
UNUSED_P(enc);
return BIG2_CHAR_MATCHES(p, c);
}
-static int PTRFASTCALL
+static int
big2_isNameMin(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return BIG2_IS_NAME_CHAR_MINBPC(p);
}
-static int PTRFASTCALL
+static int
big2_isNmstrtMin(const ENCODING *enc, const char *p) {
UNUSED_P(enc);
return BIG2_IS_NMSTRT_CHAR_MINBPC(p);
}
+static int
+big2_isInvalid4(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ return BIG2_IS_INVALID_CHAR(p, 4);
+}
+
# undef VTABLE
# define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
@@ -930,6 +966,7 @@ big2_isNmstrtMin(const ENCODING *enc, co
# define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
# define IS_NMSTRT_CHAR(enc, p, n) (0)
# define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p)
+# define IS_INVALID_CHAR(enc, p, n) BIG2_IS_INVALID_CHAR(p, n)
# define XML_TOK_IMPL_C
# include "xmltok_impl.c"
@@ -961,7 +998,7 @@ static const struct normal_encoding big2
# include "asciitab.h"
# include "latin1tab.h"
},
- STANDARD_VTABLE(big2_) NULL_VTABLE};
+ STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
#endif
@@ -979,7 +1016,7 @@ static const struct normal_encoding big2
#undef BT_COLON
#include "latin1tab.h"
},
- STANDARD_VTABLE(big2_) NULL_VTABLE};
+ STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
#if BYTEORDER != 1234
@@ -991,7 +1028,7 @@ static const struct normal_encoding inte
# include "iasciitab.h"
# include "latin1tab.h"
},
- STANDARD_VTABLE(big2_) NULL_VTABLE};
+ STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
# endif
@@ -1003,13 +1040,13 @@ static const struct normal_encoding inte
# undef BT_COLON
# include "latin1tab.h"
},
- STANDARD_VTABLE(big2_) NULL_VTABLE};
+ STANDARD_VTABLE(big2_) UTF16_NULL_VTABLE(big2_)};
#endif
#undef PREFIX
-static int FASTCALL
+static int
streqci(const char *s1, const char *s2) {
for (;;) {
char c1 = *s1++;
@@ -1030,7 +1067,7 @@ streqci(const char *s1, const char *s2)
return 1;
}
-static void PTRCALL
+static void
initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end,
POSITION *pos) {
UNUSED_P(enc);
@@ -1048,7 +1085,7 @@ toAscii(const ENCODING *enc, const char
return buf[0];
}
-static int FASTCALL
+static int
isSpace(int c) {
switch (c) {
case 0x20:
@@ -1154,6 +1191,34 @@ static const char KW_yes[] = {ASCII_y, A
static const char KW_no[] = {ASCII_n, ASCII_o, '\0'};
+static const char KW_1_dot[] = {ASCII_1, ASCII_PERIOD, '\0'};
+
+/* Checks a version pseudo-attribute value against the VersionNum production.
+ XML 1.0 Fourth Edition only allows the literal "1.0", but the Fifth
+ Edition relaxed this to "1." followed by one or more digits, since Expat
+ only implements 1.0 itself but plans to track the Fifth Edition's laxer
+ grammar here so that "1.1" and similar aren't rejected only to have that
+ rejection reverted later. Returns true for a value matching "1.[0-9]+".
+ val/valEnd bound the value itself; valEnd is the upper bound used when
+ decoding the individual characters between them. */
+static bool
+checkXmlDeclVersionNum(const ENCODING *enc, const char *val,
+ const char *valEnd) {
+ if (valEnd - val < 2 * enc->minBytesPerChar
+ || ! XmlNameMatchesAscii(enc, val, val + 2 * enc->minBytesPerChar,
+ KW_1_dot))
+ return false;
+ val += 2 * enc->minBytesPerChar;
+ if (val == valEnd)
+ return false;
+ for (; val != valEnd; val += enc->minBytesPerChar) {
+ int c = toAscii(enc, val, valEnd);
+ if (c < ASCII_0 || c > ASCII_9)
+ return false;
+ }
+ return true;
+}
+
static int
doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *,
const char *),
@@ -1188,6 +1253,15 @@ doParseXmlDecl(const ENCODING *(*encodin
*badPtr = val;
return 0;
}
+ /* Expat implements XML 1.0 only, so any version outside the "1.0"/"1.x"
+ family is rejected. Following the Fifth Edition's VersionNum
+ production (rather than the Fourth Edition's exact "1.0") avoids
+ rejecting "1.1" now only to have to revert that once Expat tracks
+ the newer edition. */
+ if (! checkXmlDeclVersionNum(enc, val, ptr - enc->minBytesPerChar)) {
+ *badPtr = val;
+ return 0;
+ }
if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
*badPtr = ptr;
return 0;
@@ -1242,7 +1316,7 @@ doParseXmlDecl(const ENCODING *(*encodin
return 1;
}
-static int FASTCALL
+static int
checkCharRefNumber(int result) {
switch (result >> 8) {
case 0xD8:
@@ -1266,7 +1340,7 @@ checkCharRefNumber(int result) {
return result;
}
-int FASTCALL
+int
XmlUtf8Encode(int c, char *buf) {
enum {
/* minN is minimum legal resulting value for N byte sequence */
@@ -1302,7 +1376,7 @@ XmlUtf8Encode(int c, char *buf) {
return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */
}
-int FASTCALL
+int
XmlUtf16Encode(int charNum, unsigned short *buf) {
if (charNum < 0)
return 0;
@@ -1334,7 +1408,7 @@ XmlSizeOfUnknownEncoding(void) {
return sizeof(struct unknown_encoding);
}
-static int PTRFASTCALL
+static int
unknown_isName(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
@@ -1343,7 +1417,7 @@ unknown_isName(const ENCODING *enc, cons
return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
}
-static int PTRFASTCALL
+static int
unknown_isNmstrt(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
@@ -1352,14 +1426,14 @@ unknown_isNmstrt(const ENCODING *enc, co
return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
}
-static int PTRFASTCALL
+static int
unknown_isInvalid(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
char **toP, const char *toLim) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
@@ -1389,7 +1463,7 @@ unknown_toUtf8(const ENCODING *enc, cons
}
}
-static enum XML_Convert_Result PTRCALL
+static enum XML_Convert_Result
unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
unsigned short **toP, const unsigned short *toLim) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
@@ -1513,7 +1587,7 @@ static const char KW_UTF_16LE[]
= {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
ASCII_6, ASCII_L, ASCII_E, '\0'};
-static int FASTCALL
+static int
getEncodingIndex(const char *name) {
static const char *const encodingNames[] = {
KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
Index: lib/libexpat/lib/xmltok.h
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmltok.h,v
diff -u -p -r1.9.6.2 xmltok.h
--- lib/libexpat/lib/xmltok.h 10 Sep 2026 20:46:02 -0000 1.9.6.2
+++ lib/libexpat/lib/xmltok.h 2 Oct 2026 22:01:22 -0000
@@ -163,8 +163,8 @@ typedef struct {
struct encoding;
typedef struct encoding ENCODING;
-typedef int(PTRCALL *SCANNER)(const ENCODING *, const char *, const char *,
- const char **);
+typedef int (*SCANNER)(const ENCODING *, const char *, const char *,
+ const char **);
enum XML_Convert_Result {
XML_CONVERT_COMPLETED = 0,
@@ -176,28 +176,27 @@ enum XML_Convert_Result {
struct encoding {
SCANNER scanners[XML_N_STATES];
SCANNER literalScanners[XML_N_LITERAL_TYPES];
- int(PTRCALL *nameMatchesAscii)(const ENCODING *, const char *, const char *,
- const char *);
- int(PTRFASTCALL *nameLength)(const ENCODING *, const char *);
- const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *);
- int(PTRCALL *getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
- ATTRIBUTE *atts);
- int(PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr);
- int(PTRCALL *predefinedEntityName)(const ENCODING *, const char *,
- const char *);
- void(PTRCALL *updatePosition)(const ENCODING *, const char *ptr,
- const char *end, POSITION *);
- int(PTRCALL *isPublicId)(const ENCODING *enc, const char *ptr,
- const char *end, const char **badPtr);
- enum XML_Convert_Result(PTRCALL *utf8Convert)(const ENCODING *enc,
- const char **fromP,
- const char *fromLim, char **toP,
- const char *toLim);
- enum XML_Convert_Result(PTRCALL *utf16Convert)(const ENCODING *enc,
- const char **fromP,
- const char *fromLim,
- unsigned short **toP,
- const unsigned short *toLim);
+ int (*nameMatchesAscii)(const ENCODING *, const char *, const char *,
+ const char *);
+ int (*nameLength)(const ENCODING *, const char *);
+ const char *(*skipS)(const ENCODING *, const char *);
+ int (*getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
+ ATTRIBUTE *atts);
+ int (*charRefNumber)(const ENCODING *enc, const char *ptr);
+ int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
+ void (*updatePosition)(const ENCODING *, const char *ptr, const char *end,
+ POSITION *);
+ int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr);
+ enum XML_Convert_Result (*utf8Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim, char **toP,
+ const char *toLim);
+ enum XML_Convert_Result (*utf16Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ unsigned short **toP,
+ const unsigned short *toLim);
int minBytesPerChar;
char isUtf8;
char isUtf16;
@@ -297,8 +296,8 @@ int XmlInitEncoding(INIT_ENCODING *p, co
const char *name);
const ENCODING *XmlGetUtf8InternalEncoding(void);
const ENCODING *XmlGetUtf16InternalEncoding(void);
-int FASTCALL XmlUtf8Encode(int charNumber, char *buf);
-int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf);
+int XmlUtf8Encode(int charNumber, char *buf);
+int XmlUtf16Encode(int charNumber, unsigned short *buf);
int XmlSizeOfUnknownEncoding(void);
typedef int(XMLCALL *CONVERTER)(void *userData, const char *p);
Index: lib/libexpat/lib/xmltok_impl.c
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmltok_impl.c,v
diff -u -p -r1.18.12.1 xmltok_impl.c
--- lib/libexpat/lib/xmltok_impl.c 20 Aug 2026 07:49:22 -0000 1.18.12.1
+++ lib/libexpat/lib/xmltok_impl.c 2 Oct 2026 22:01:22 -0000
@@ -44,10 +44,6 @@
#ifdef XML_TOK_IMPL_C
-# ifndef IS_INVALID_CHAR // i.e. for UTF-16 and XML_MIN_SIZE not defined
-# define IS_INVALID_CHAR(enc, ptr, n) (0)
-# endif
-
# define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
case BT_LEAD##n: \
if (end - ptr < n) \
@@ -144,7 +140,7 @@
/* ptr points to character following "= end)
@@ -430,7 +426,7 @@ PREFIX(cdataSectionTok)(const ENCODING *
/* ptr points to character following "" */
-static int PTRCALL
+static int
PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -481,7 +477,7 @@ PREFIX(scanEndTag)(const ENCODING *enc,
/* ptr points to character following "" */
-static int PTRCALL
+static int
PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
if (HAS_CHAR(enc, ptr, end)) {
@@ -512,7 +508,7 @@ PREFIX(scanHexCharRef)(const ENCODING *e
/* ptr points to character following "" */
-static int PTRCALL
+static int
PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
if (HAS_CHAR(enc, ptr, end)) {
@@ -543,7 +539,7 @@ PREFIX(scanCharRef)(const ENCODING *enc,
/* ptr points to character following "&" */
-static int PTRCALL
+static int
PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -571,7 +567,7 @@ PREFIX(scanRef)(const ENCODING *enc, con
/* ptr points to character following first character of attribute name */
-static int PTRCALL
+static int
PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
# ifdef XML_NS
@@ -724,7 +720,7 @@ PREFIX(scanAtts)(const ENCODING *enc, co
/* ptr points to character following "<" */
-static int PTRCALL
+static int
PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
# ifdef XML_NS
@@ -822,7 +818,7 @@ PREFIX(scanLt)(const ENCODING *enc, cons
return XML_TOK_PARTIAL;
}
-static int PTRCALL
+static int
PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
if (ptr >= end)
@@ -922,7 +918,7 @@ PREFIX(contentTok)(const ENCODING *enc,
/* ptr points to character following "%" */
-static int PTRCALL
+static int
PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -952,7 +948,7 @@ PREFIX(scanPercent)(const ENCODING *enc,
return XML_TOK_PARTIAL;
}
-static int PTRCALL
+static int
PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
@@ -982,7 +978,7 @@ PREFIX(scanPoundName)(const ENCODING *en
return -XML_TOK_POUND_NAME;
}
-static int PTRCALL
+static int
PREFIX(scanLit)(int open, const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
while (HAS_CHAR(enc, ptr, end)) {
@@ -1016,7 +1012,7 @@ PREFIX(scanLit)(int open, const ENCODING
return XML_TOK_PARTIAL;
}
-static int PTRCALL
+static int
PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
int tok;
@@ -1260,7 +1256,7 @@ PREFIX(prologTok)(const ENCODING *enc, c
return -tok;
}
-static int PTRCALL
+static int
PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
const char *start;
@@ -1329,7 +1325,7 @@ PREFIX(attributeValueTok)(const ENCODING
return XML_TOK_DATA_CHARS;
}
-static int PTRCALL
+static int
PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
const char *start;
@@ -1396,7 +1392,7 @@ PREFIX(entityValueTok)(const ENCODING *e
# ifdef XML_DTD
-static int PTRCALL
+static int
PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
int level = 0;
@@ -1448,7 +1444,7 @@ PREFIX(ignoreSectionTok)(const ENCODING
# endif /* XML_DTD */
-static int PTRCALL
+static int
PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
const char **badPtr) {
ptr += MINBPC(enc);
@@ -1508,7 +1504,7 @@ PREFIX(isPublicId)(const ENCODING *enc,
first attsMax attributes are stored in atts.
*/
-static int PTRCALL
+static int
PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
ATTRIBUTE *atts) {
enum { other, inName, inValue } state = inName;
@@ -1601,7 +1597,7 @@ PREFIX(getAtts)(const ENCODING *enc, con
/* not reached */
}
-static int PTRFASTCALL
+static int
PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) {
int result = 0;
/* skip */
@@ -1659,7 +1655,7 @@ PREFIX(charRefNumber)(const ENCODING *en
return checkCharRefNumber(result);
}
-static int PTRCALL
+static int
PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr,
const char *end) {
UNUSED_P(enc);
@@ -1713,7 +1709,7 @@ PREFIX(predefinedEntityName)(const ENCOD
return 0;
}
-static int PTRCALL
+static int
PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
const char *end1, const char *ptr2) {
UNUSED_P(enc);
@@ -1732,7 +1728,7 @@ PREFIX(nameMatchesAscii)(const ENCODING
return ptr1 == end1;
}
-static int PTRFASTCALL
+static int
PREFIX(nameLength)(const ENCODING *enc, const char *ptr) {
const char *start = ptr;
for (;;) {
@@ -1762,7 +1758,7 @@ PREFIX(nameLength)(const ENCODING *enc,
}
}
-static const char *PTRFASTCALL
+static const char *
PREFIX(skipS)(const ENCODING *enc, const char *ptr) {
for (;;) {
switch (BYTE_TYPE(enc, ptr)) {
@@ -1777,7 +1773,7 @@ PREFIX(skipS)(const ENCODING *enc, const
}
}
-static void PTRCALL
+static void
PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end,
POSITION *pos) {
while (HAS_CHAR(enc, ptr, end)) {
Index: lib/libexpat/lib/xmltok_ns.c
===================================================================
RCS file: /cvs/src/lib/libexpat/lib/xmltok_ns.c,v
diff -u -p -r1.9.4.1 xmltok_ns.c
--- lib/libexpat/lib/xmltok_ns.c 20 Aug 2026 07:49:22 -0000 1.9.4.1
+++ lib/libexpat/lib/xmltok_ns.c 2 Oct 2026 22:01:22 -0000
@@ -64,14 +64,14 @@ static const ENCODING *const NS(encoding
&ns(utf8_encoding).enc /* NO_ENC */
};
-static int PTRCALL
+static int
NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE,
ptr, end, nextTokPtr);
}
-static int PTRCALL
+static int
NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr) {
return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE,
Index: lib/libexpat/tests/basic_tests.c
===================================================================
RCS file: /cvs/src/lib/libexpat/tests/basic_tests.c,v
diff -u -p -r1.9.4.2 basic_tests.c
--- lib/libexpat/tests/basic_tests.c 10 Sep 2026 20:46:02 -0000 1.9.4.2
+++ lib/libexpat/tests/basic_tests.c 2 Oct 2026 22:01:22 -0000
@@ -974,6 +974,50 @@ START_TEST(test_xmldecl_empty_version) {
}
END_TEST
+/* Regression test for GH #967: Expat only implements XML 1.0 Fourth
+ Edition, so a declared version outside the "1.x" family must be
+ rejected rather than silently accepted. A version matching the Fifth
+ Edition's VersionNum production ("1." followed by one or more digits)
+ is accepted even though Expat itself only implements 1.0 Fourth
+ Edition, per GH #967's review thread: rejecting "1.1" now would just
+ have to be reverted once Expat tracks the Fifth Edition, so it's let
+ through rather than blocked twice. */
+START_TEST(test_xmldecl_wrong_version_number) {
+ const char *const badVersions[] = {"2.3", "0.9", "10", "1.", "1", " 1.0 "};
+
+ for (size_t i = 0; i < sizeof(badVersions) / sizeof(badVersions[0]); i++) {
+ char doc[64];
+ snprintf(doc, sizeof(doc), "\n", badVersions[i]);
+ set_subtest("version='%s'", badVersions[i]);
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), XML_TRUE)
+ == XML_STATUS_ERROR);
+ assert_true(XML_GetErrorCode(parser) == XML_ERROR_XML_DECL);
+ XML_ParserFree(parser);
+ }
+}
+END_TEST
+
+/* GH #967's review pointed out that XML 1.0 Fifth Edition relaxed
+ VersionNum to "1." followed by one or more digits, so versions like
+ "1.1" and "1.123" should parse rather than being rejected. */
+START_TEST(test_xmldecl_accepts_1_x_version) {
+ const char *const goodVersions[] = {"1.1", "1.123"};
+
+ for (size_t i = 0; i < sizeof(goodVersions) / sizeof(goodVersions[0]); i++) {
+ char doc[64];
+ snprintf(doc, sizeof(doc), "\n", goodVersions[i]);
+ set_subtest("version='%s'", goodVersions[i]);
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), XML_TRUE)
+ == XML_STATUS_OK);
+ XML_ParserFree(parser);
+ }
+}
+END_TEST
+
/* Regression test for SF bug #584832. */
START_TEST(test_unknown_encoding_internal_entity) {
const char *text = "\n"
@@ -1822,6 +1866,301 @@ START_TEST(test_utf16_bad_surrogate_pair
}
END_TEST
+// Helper that creates a UTF-16LE copy of UTF-16BE literal input and vice versa
+static char *
+utf16_dup_flipped(const char *text, size_t lenBytes) {
+ assert_true(lenBytes < SIZE_MAX);
+ assert_true(lenBytes % 2 == 0);
+ char *const buffer = malloc(lenBytes + 1);
+ assert_true(buffer != NULL);
+
+ for (size_t i = 0; i < lenBytes; i++) {
+ // This maps 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, 4 -> 5, ..
+ size_t j = i + ((i % 2 == 0) ? +1 : -1);
+ assert_true(j < lenBytes);
+ buffer[j] = text[i];
+ }
+
+ buffer[lenBytes] = '\0';
+
+ return buffer;
+}
+
+/* Tests that invalid combinations of surrogates are detected when decoding
+ UTF-16, both little-endian and big-endian.
+ Previously, a high surrogate not followed by a low surrogate slipped
+ through. Without validation the high would consume the next
+ code unit as a fake low, hiding e.g. a following '<' from the
+ tokenizer. */
+START_TEST(test_utf16_surrogate_pairs) {
+ struct TestCase {
+ const char *idea;
+ const char *content;
+ bool expectedSuccess;
+ };
+
+ struct TestCase testCases[] = {
+ // Group {smallest high - 1}{*}
+ {"{smallest high - 1}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ true},
+ {"{smallest high - 1}{smallest high}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high - 1}{largest high}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high - 1}{smallest low}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high - 1}{largest low}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high - 1}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xD7\xFF"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ true},
+ // Group {smallest high}{*}
+ {"{smallest high}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high}{smallest high}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high}{largest high}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest high}{smallest low}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ true},
+ {"{smallest high}{largest low}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ true},
+ {"{smallest high}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xD8\x00"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ false},
+ // Group {largest high}{*}
+ {"{largest high}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest high}{smallest high}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest high}{largest high}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest high}{smallest low}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ true},
+ {"{largest high}{largest low}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ true},
+ {"{largest high}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xDB\xFF"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ false},
+ // Group {smallest low}{*}
+ {"{smallest low}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{smallest high}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{largest high}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{smallest low}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{largest low}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{smallest low}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xDC\x00"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ false},
+ // Group {largest low}{*}
+ {"{largest low}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{smallest high}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{largest high}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{smallest low}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{largest low}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xDF\xFF"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ false},
+ // Group {largest low + 1}{*}
+ {"{largest low + 1}{smallest high - 1}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xD7\xFF"
+ "\0<\0/\0a\0>",
+ true},
+ {"{largest low + 1}{smallest high}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xD8\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low + 1}{largest high}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xDB\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low + 1}{smallest low}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xDC\x00"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low + 1}{largest low}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xDF\xFF"
+ "\0<\0/\0a\0>",
+ false},
+ {"{largest low + 1}{largest low + 1}",
+ "\0<\0a\0>"
+ "\xE0\x00"
+ "\xE0\x00"
+ "\0<\0/\0a\0>",
+ true},
+ };
+
+ for (size_t i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++) {
+ set_subtest("%s", testCases[i].idea);
+
+ const int lenBytes = /**/ 6 + /*first*/ 2 + /*second*/ 2 + /**/ 8;
+ const bool expectedSuccess = testCases[i].expectedSuccess;
+ const enum XML_Status expectedStatus
+ = (expectedSuccess ? XML_STATUS_OK : XML_STATUS_ERROR);
+
+ const char *const bigEndian = testCases[i].content;
+ char *const littleEndian = utf16_dup_flipped(bigEndian, lenBytes);
+ assert_true(littleEndian != NULL);
+ const char *endianCases[] = {bigEndian, littleEndian};
+
+ for (size_t j = 0; j < sizeof(endianCases) / sizeof(endianCases[0]); j++) {
+ const char *text = endianCases[j];
+
+ assert_true(text[lenBytes] == '\0'); // self-test
+ assert_true((text[0] == '\0')
+ != (text[lenBytes - 1] == '\0')); // self-test
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(parser != NULL);
+
+ assert_true(_XML_Parse_SINGLE_BYTES(parser, text, lenBytes, XML_TRUE)
+ == expectedStatus);
+ if (! expectedSuccess) {
+ assert_true(XML_GetErrorCode(parser) == XML_ERROR_INVALID_TOKEN);
+ }
+
+ XML_ParserFree(parser);
+ }
+
+ free(littleEndian);
+ }
+}
+END_TEST
+
START_TEST(test_bad_cdata) {
struct CaseData {
const char *text;
@@ -6735,6 +7074,8 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_xmldecl_missing_attr);
tcase_add_test(tc_basic, test_xmldecl_missing_value);
tcase_add_test(tc_basic, test_xmldecl_empty_version);
+ tcase_add_test(tc_basic, test_xmldecl_wrong_version_number);
+ tcase_add_test(tc_basic, test_xmldecl_accepts_1_x_version);
tcase_add_test__if_xml_ge(tc_basic, test_unknown_encoding_internal_entity);
tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_set_encoding);
@@ -6768,6 +7109,7 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_long_cdata_utf16);
tcase_add_test(tc_basic, test_multichar_cdata_utf16);
tcase_add_test(tc_basic, test_utf16_bad_surrogate_pair);
+ tcase_add_test(tc_basic, test_utf16_surrogate_pairs);
tcase_add_test(tc_basic, test_bad_cdata);
tcase_add_test(tc_basic, test_bad_cdata_utf16);
tcase_add_test(tc_basic, test_stop_parser_between_cdata_calls);
Index: lib/libexpat/tests/memcheck.c
===================================================================
RCS file: /cvs/src/lib/libexpat/tests/memcheck.c,v
diff -u -p -r1.6.12.1 memcheck.c
--- lib/libexpat/tests/memcheck.c 20 Aug 2026 07:49:22 -0000 1.6.12.1
+++ lib/libexpat/tests/memcheck.c 2 Oct 2026 22:01:22 -0000
@@ -117,7 +117,7 @@ tracking_free(void *ptr) {
if (entry->next != NULL)
entry->next->prev = entry->prev;
else
- alloc_tail = entry->next;
+ alloc_tail = entry->prev;
free(entry);
} else {
printf("Attempting to free unallocated memory at %p\n", ptr);
Index: lib/libexpat/tests/nsalloc_tests.c
===================================================================
RCS file: /cvs/src/lib/libexpat/tests/nsalloc_tests.c,v
diff -u -p -r1.3.4.1 nsalloc_tests.c
--- lib/libexpat/tests/nsalloc_tests.c 20 Aug 2026 07:49:22 -0000 1.3.4.1
+++ lib/libexpat/tests/nsalloc_tests.c 2 Oct 2026 22:01:22 -0000
@@ -43,6 +43,8 @@
SPDX-License-Identifier: MIT
*/
+#include "expat_config.h"
+
#if defined(NDEBUG)
# undef NDEBUG /* because test suite relies on assert(...) at the moment */
#endif