MFV: expat 2.7.3.

MFC after:	3 days
This commit is contained in:
Xin LI
2025-09-28 21:28:11 -07:00
15 changed files with 251 additions and 53 deletions
+56 -2
View File
@@ -41,6 +41,59 @@
!! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !! !! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Release 2.7.3 Wed September 24 2025
Security fixes:
#1046 #1048 Fix alignment of internal allocations for some non-amd64
architectures (e.g. sparc32); fixes up on the fix to
CVE-2025-59375 from #1034 (of Expat 2.7.2 and related
backports)
#1059 Fix a class of false positives where input should have been
rejected with error XML_ERROR_ASYNC_ENTITY; regression from
CVE-2024-8176 fix pull request #973 (of Expat 2.7.0 and
related backports). Please check the added unit tests for
example documents.
Other changes:
#1043 Prove and regression-proof absence of integer overflow
from function expat_realloc
#1062 Remove "harmless" cast that truncated a size_t to unsigned
#1049 Autotools: Remove "ln -s" discovery
#1054 docs: Be consistent with use of floating point around
XML_SetAllocTrackerMaximumAmplification
#1056 docs: Make it explicit that XML_GetCurrentColumnNumber
starts at 0
#1057 docs: Better integrate the effect of the activation
thresholds
#1058 docs: Fix an in-comment typo in expat.h
#1045 docs: Fix a typo in README.md
#1041 docs: Improve change log of release 2.7.2
#1053 xmlwf: Resolve use of functions XML_GetErrorLineNumber
and XML_GetErrorColumnNumber
#1032 Windows: Normalize .bat files to CRLF line endings
#1060 #1061 Version info bumped from 12:0:11 (libexpat*.so.1.11.0)
to 12:1:11 (libexpat*.so.1.11.1); see https://verbump.de/
for what these numbers do
Infrastructure:
#1047 #1050 CI: Cleanup UndefinedBehaviorSanitizer fatality
#1044 CI|Linux: Stop aborting at first job failure
#1052 CI|FreeBSD: Upgrade to FreeBSD 15.0
#1039 CI|FreeBSD: Do not install CMake meta-package
Special thanks to:
Bénédikt Tran
Berkay Eren Ürün
Daniel Engberg
Hanno Böck
Matthew Fernandez
Rolf Eike Beer
Sam James
Tim Bray
and
Clang/GCC UndefinedBehaviorSanitizer
OSS-Fuzz / ClusterFuzz
Z3 Theorem Prover
Release 2.7.2 Tue September 16 2025 Release 2.7.2 Tue September 16 2025
Security fixes: Security fixes:
#1018 #1034 CVE-2025-59375 -- Disallow use of disproportional amounts of #1018 #1034 CVE-2025-59375 -- Disallow use of disproportional amounts of
@@ -73,7 +126,7 @@ Release 2.7.2 Tue September 16 2025
to the pull request URL could be of help. to the pull request URL could be of help.
Other changes: Other changes:
#1008 #1017 Autotools: Sync CMake templates with CMake 3.31 for macOS #1008 #1017 Autotools|macOS: Sync CMake templates with CMake 3.31
#1007 CMake: Drop support for CMake <3.15 #1007 CMake: Drop support for CMake <3.15
#1004 CMake: Fix off_t detection for -Werror #1004 CMake: Fix off_t detection for -Werror
#1007 CMake|Windows: Fix -DEXPAT_MSVC_STATIC_CRT=ON #1007 CMake|Windows: Fix -DEXPAT_MSVC_STATIC_CRT=ON
@@ -89,7 +142,7 @@ Release 2.7.2 Tue September 16 2025
#994 docs: Drop AppVeyor badge #994 docs: Drop AppVeyor badge
#1000 tests: Fix portable_strndup #1000 tests: Fix portable_strndup
#1036 Drop casts around malloc/free/realloc that C99 does not need #1036 Drop casts around malloc/free/realloc that C99 does not need
#1010 Replace empty for-loops with while loops #1010 Replace empty for loops with while loops
#1011 Add const with internal XmlInitUnknownEncodingNS #1011 Add const with internal XmlInitUnknownEncodingNS
#14 #1037 Drop an OpenVMS support leftover #14 #1037 Drop an OpenVMS support leftover
#999 #1001 Address more clang-tidy warnings #999 #1001 Address more clang-tidy warnings
@@ -111,6 +164,7 @@ Release 2.7.2 Tue September 16 2025
Neil Pang Neil Pang
Theo Buehler Theo Buehler
and and
GNU Time
OSS-Fuzz / ClusterFuzz OSS-Fuzz / ClusterFuzz
Perl XML::Parser Perl XML::Parser
+2 -2
View File
@@ -11,7 +11,7 @@
> at the top of the `Changes` file. > at the top of the `Changes` file.
# Expat, Release 2.7.2 # Expat, Release 2.7.3
This is Expat, a C99 library for parsing This is Expat, a C99 library for parsing
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by [XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by
@@ -120,7 +120,7 @@ project(hello VERSION 1.0.0)
FetchContent_Declare( FetchContent_Declare(
expat expat
GIT_REPOSITORY https://github.com/libexpat/libexpat/ GIT_REPOSITORY https://github.com/libexpat/libexpat/
GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_0_Y_Z GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_X_Y_Z
SOURCE_SUBDIR expat/ SOURCE_SUBDIR expat/
) )
+2 -2
View File
@@ -24,6 +24,7 @@ dnl Copyright (c) 2019 Kishore Kunche <kishore.kunche@intel.com>
dnl Copyright (c) 2020 Jeffrey Walton <noloader@gmail.com> dnl Copyright (c) 2020 Jeffrey Walton <noloader@gmail.com>
dnl Copyright (c) 2024 Ferenc Géczi <ferenc.gm@gmail.com> dnl Copyright (c) 2024 Ferenc Géczi <ferenc.gm@gmail.com>
dnl Copyright (c) 2024 Dag-Erling Smørgrav <des@des.dev> dnl Copyright (c) 2024 Dag-Erling Smørgrav <des@des.dev>
dnl Copyright (c) 2025 Matthew Fernandez <matthew.fernandez@gmail.com>
dnl Licensed under the MIT license: dnl Licensed under the MIT license:
dnl dnl
dnl Permission is hereby granted, free of charge, to any person obtaining dnl Permission is hereby granted, free of charge, to any person obtaining
@@ -85,7 +86,7 @@ dnl If the API changes incompatibly set LIBAGE back to 0
dnl dnl
LIBCURRENT=12 # sync LIBCURRENT=12 # sync
LIBREVISION=0 # with LIBREVISION=1 # with
LIBAGE=11 # CMakeLists.txt! LIBAGE=11 # CMakeLists.txt!
AC_CONFIG_HEADERS([expat_config.h]) AC_CONFIG_HEADERS([expat_config.h])
@@ -95,7 +96,6 @@ AH_BOTTOM([#endif // ndef EXPAT_CONFIG_H])
AM_PROG_AR AM_PROG_AR
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
LT_PREREQ([2.4]) LT_PREREQ([2.4])
+12 -6
View File
@@ -52,7 +52,7 @@
<div> <div>
<h1> <h1>
The Expat XML Parser The Expat XML Parser
<small>Release 2.7.2</small> <small>Release 2.7.3</small>
</h1> </h1>
</div> </div>
<div class="content"> <div class="content">
@@ -2137,8 +2137,8 @@ XML_Size XMLCALL
XML_GetCurrentColumnNumber(XML_Parser p); XML_GetCurrentColumnNumber(XML_Parser p);
</pre> </pre>
<div class="fcndef"> <div class="fcndef">
Return the offset, from the beginning of the current line, of Return the <em>offset</em>, from the beginning of the current line, of
the position. the position. The first column is reported as <code>0</code>.
</div> </div>
<h4 id="XML_GetCurrentByteCount">XML_GetCurrentByteCount</h4> <h4 id="XML_GetCurrentByteCount">XML_GetCurrentByteCount</h4>
@@ -2200,7 +2200,10 @@ XML_SetBillionLaughsAttackProtectionMaximumAmplification(XML_Parser p,
returns <code>XML_TRUE</code> upon success and <code>XML_FALSE</code> upon error. returns <code>XML_TRUE</code> upon success and <code>XML_FALSE</code> upon error.
</p> </p>
<p>The amplification factor is calculated as ..</p> <p>
Once the <a href="#XML_SetBillionLaughsAttackProtectionActivationThreshold">threshold for activation</a> is reached,
the amplification factor is calculated as ..
</p>
<pre>amplification := (direct + indirect) / direct</pre> <pre>amplification := (direct + indirect) / direct</pre>
<p> <p>
.. while parsing, whereas .. while parsing, whereas
@@ -2317,7 +2320,10 @@ XML_SetAllocTrackerMaximumAmplification(XML_Parser p,
</li> </li>
</ul> </ul>
<p>The amplification factor is calculated as ..</p> <p>
Once the <a href="#XML_SetAllocTrackerActivationThreshold">threshold for activation</a> is reached,
the amplification factor is calculated as ..
</p>
<pre>amplification := allocated / direct</pre> <pre>amplification := allocated / direct</pre>
<p> <p>
.. while parsing, whereas .. while parsing, whereas
@@ -2339,7 +2345,7 @@ XML_SetAllocTrackerMaximumAmplification(XML_Parser p,
<p> <p>
<strong>Note:</strong> <strong>Note:</strong>
Amplifications factors greater than 100 can been observed near the start of parsing Amplifications factors greater than <code>100.0</code> can been observed near the start of parsing
even with benign files in practice. even with benign files in practice.
So if you do reduce the maximum allowed amplification, So if you do reduce the maximum allowed amplification,
+1 -1
View File
@@ -5,7 +5,7 @@
\\$2 \(la\\$1\(ra\\$3 \\$2 \(la\\$1\(ra\\$3
.. ..
.if \n(.g .mso www.tmac .if \n(.g .mso www.tmac
.TH XMLWF 1 "September 16, 2025" "" "" .TH XMLWF 1 "September 24, 2025" "" ""
.SH NAME .SH NAME
xmlwf \- Determines if an XML document is well-formed xmlwf \- Determines if an XML document is well-formed
.SH SYNOPSIS .SH SYNOPSIS
+1 -1
View File
@@ -21,7 +21,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
<!ENTITY dhfirstname "<firstname>Scott</firstname>"> <!ENTITY dhfirstname "<firstname>Scott</firstname>">
<!ENTITY dhsurname "<surname>Bronson</surname>"> <!ENTITY dhsurname "<surname>Bronson</surname>">
<!ENTITY dhdate "<date>September 16, 2025</date>"> <!ENTITY dhdate "<date>September 24, 2025</date>">
<!-- Please adjust this^^ date whenever cutting a new release. --> <!-- Please adjust this^^ date whenever cutting a new release. -->
<!ENTITY dhsection "<manvolnum>1</manvolnum>"> <!ENTITY dhsection "<manvolnum>1</manvolnum>">
<!ENTITY dhemail "<email>bronson@rinspin.com</email>"> <!ENTITY dhemail "<email>bronson@rinspin.com</email>">
+3 -2
View File
@@ -19,6 +19,7 @@
Copyright (c) 2023 Hanno Böck <hanno@gentoo.org> Copyright (c) 2023 Hanno Böck <hanno@gentoo.org>
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com> Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp> Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp>
Copyright (c) 2025 Matthew Fernandez <matthew.fernandez@gmail.com>
Licensed under the MIT license: Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
@@ -276,7 +277,7 @@ XML_ParserCreate_MM(const XML_Char *encoding,
/* Prepare a parser object to be reused. This is particularly /* Prepare a parser object to be reused. This is particularly
valuable when memory allocation overhead is disproportionately high, valuable when memory allocation overhead is disproportionately high,
such as when a large number of small documnents need to be parsed. such as when a large number of small documents need to be parsed.
All handlers are cleared from the parser, except for the All handlers are cleared from the parser, except for the
unknownEncodingHandler. The parser's external state is re-initialized unknownEncodingHandler. The parser's external state is re-initialized
except for the values of ns and ns_triplets. except for the values of ns and ns_triplets.
@@ -1081,7 +1082,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
*/ */
# define XML_MAJOR_VERSION 2 # define XML_MAJOR_VERSION 2
# define XML_MINOR_VERSION 7 # define XML_MINOR_VERSION 7
# define XML_MICRO_VERSION 2 # define XML_MICRO_VERSION 3
# ifdef __cplusplus # ifdef __cplusplus
} }
+6
View File
@@ -108,6 +108,7 @@
#endif #endif
#include <limits.h> // ULONG_MAX #include <limits.h> // ULONG_MAX
#include <stddef.h> // size_t
#if defined(_WIN32) \ #if defined(_WIN32) \
&& (! defined(__USE_MINGW_ANSI_STDIO) \ && (! defined(__USE_MINGW_ANSI_STDIO) \
@@ -153,6 +154,11 @@
#define EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT \ #define EXPAT_ALLOC_TRACKER_ACTIVATION_THRESHOLD_DEFAULT \
67108864 // 64 MiB, 2^26 67108864 // 64 MiB, 2^26
// 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
#define EXPAT_MALLOC_PADDING ((EXPAT_MALLOC_ALIGNMENT) - sizeof(size_t))
/* NOTE END */ /* NOTE END */
#include "expat.h" // so we can use type XML_Parser below #include "expat.h" // so we can use type XML_Parser below
+32 -17
View File
@@ -1,4 +1,4 @@
/* 60e137abb91af642d6c3988f8f133d23329b32638659c74d47125fc0faf6ddd5 (2.7.2+) /* 28bcd8b1ba7eb595d82822908257fd9c3589b4243e3c922d0369f35bfcd7b506 (2.7.3+)
__ __ _ __ __ _
___\ \/ /_ __ __ _| |_ ___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __| / _ \\ /| '_ \ / _` | __|
@@ -41,6 +41,7 @@
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com> Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024-2025 Berkay Eren Ürün <berkay.ueruen@siemens.com> Copyright (c) 2024-2025 Berkay Eren Ürün <berkay.ueruen@siemens.com>
Copyright (c) 2024 Hanno Böck <hanno@gentoo.org> Copyright (c) 2024 Hanno Böck <hanno@gentoo.org>
Copyright (c) 2025 Matthew Fernandez <matthew.fernandez@gmail.com>
Licensed under the MIT license: Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
@@ -850,14 +851,14 @@ static void *
# endif # endif
expat_malloc(XML_Parser parser, size_t size, int sourceLine) { expat_malloc(XML_Parser parser, size_t size, int sourceLine) {
// Detect integer overflow // Detect integer overflow
if (SIZE_MAX - size < sizeof(size_t)) { if (SIZE_MAX - size < sizeof(size_t) + EXPAT_MALLOC_PADDING) {
return NULL; return NULL;
} }
const XML_Parser rootParser = getRootParserOf(parser, NULL); const XML_Parser rootParser = getRootParserOf(parser, NULL);
assert(rootParser->m_parentParser == NULL); assert(rootParser->m_parentParser == NULL);
const size_t bytesToAllocate = sizeof(size_t) + size; const size_t bytesToAllocate = sizeof(size_t) + EXPAT_MALLOC_PADDING + size;
if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated if ((XmlBigCount)-1 - rootParser->m_alloc_tracker.bytesAllocated
< bytesToAllocate) { < bytesToAllocate) {
@@ -894,7 +895,7 @@ expat_malloc(XML_Parser parser, size_t size, int sourceLine) {
rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine); rootParser->m_alloc_tracker.peakBytesAllocated, sourceLine);
} }
return (char *)mallocedPtr + sizeof(size_t); return (char *)mallocedPtr + sizeof(size_t) + EXPAT_MALLOC_PADDING;
} }
# if defined(XML_TESTING) # if defined(XML_TESTING)
@@ -914,8 +915,9 @@ expat_free(XML_Parser parser, void *ptr, int sourceLine) {
// Extract size (to the eyes of malloc_fcn/realloc_fcn) and // Extract size (to the eyes of malloc_fcn/realloc_fcn) and
// the original pointer returned by malloc/realloc // the original pointer returned by malloc/realloc
void *const mallocedPtr = (char *)ptr - sizeof(size_t); void *const mallocedPtr = (char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t);
const size_t bytesAllocated = sizeof(size_t) + *(size_t *)mallocedPtr; const size_t bytesAllocated
= sizeof(size_t) + EXPAT_MALLOC_PADDING + *(size_t *)mallocedPtr;
// Update accounting // Update accounting
assert(rootParser->m_alloc_tracker.bytesAllocated >= bytesAllocated); assert(rootParser->m_alloc_tracker.bytesAllocated >= bytesAllocated);
@@ -954,7 +956,7 @@ expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) {
// Extract original size (to the eyes of the caller) and the original // Extract original size (to the eyes of the caller) and the original
// pointer returned by malloc/realloc // pointer returned by malloc/realloc
void *mallocedPtr = (char *)ptr - sizeof(size_t); void *mallocedPtr = (char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t);
const size_t prevSize = *(size_t *)mallocedPtr; const size_t prevSize = *(size_t *)mallocedPtr;
// Classify upcoming change // Classify upcoming change
@@ -969,8 +971,13 @@ expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) {
} }
} }
// NOTE: Integer overflow detection has already been done for us
// by expat_heap_increase_tolerable(..) above
assert(SIZE_MAX - sizeof(size_t) - EXPAT_MALLOC_PADDING >= size);
// Actually allocate // Actually allocate
mallocedPtr = parser->m_mem.realloc_fcn(mallocedPtr, sizeof(size_t) + size); mallocedPtr = parser->m_mem.realloc_fcn(
mallocedPtr, sizeof(size_t) + EXPAT_MALLOC_PADDING + size);
if (mallocedPtr == NULL) { if (mallocedPtr == NULL) {
return NULL; return NULL;
@@ -1001,7 +1008,7 @@ expat_realloc(XML_Parser parser, void *ptr, size_t size, int sourceLine) {
// Update in-block recorded size // Update in-block recorded size
*(size_t *)mallocedPtr = size; *(size_t *)mallocedPtr = size;
return (char *)mallocedPtr + sizeof(size_t); return (char *)mallocedPtr + sizeof(size_t) + EXPAT_MALLOC_PADDING;
} }
#endif // XML_GE == 1 #endif // XML_GE == 1
@@ -1337,7 +1344,8 @@ parserCreate(const XML_Char *encodingName,
XML_Parser parser = NULL; XML_Parser parser = NULL;
#if XML_GE == 1 #if XML_GE == 1
const size_t increase = sizeof(size_t) + sizeof(struct XML_ParserStruct); const size_t increase
= sizeof(size_t) + EXPAT_MALLOC_PADDING + sizeof(struct XML_ParserStruct);
if (parentParser != NULL) { if (parentParser != NULL) {
const XML_Parser rootParser = getRootParserOf(parentParser, NULL); const XML_Parser rootParser = getRootParserOf(parentParser, NULL);
@@ -1352,11 +1360,13 @@ parserCreate(const XML_Char *encodingName,
if (memsuite) { if (memsuite) {
XML_Memory_Handling_Suite *mtemp; XML_Memory_Handling_Suite *mtemp;
#if XML_GE == 1 #if XML_GE == 1
void *const sizeAndParser = memsuite->malloc_fcn( void *const sizeAndParser
sizeof(size_t) + sizeof(struct XML_ParserStruct)); = memsuite->malloc_fcn(sizeof(size_t) + EXPAT_MALLOC_PADDING
+ sizeof(struct XML_ParserStruct));
if (sizeAndParser != NULL) { if (sizeAndParser != NULL) {
*(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct); *(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct);
parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)); parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)
+ EXPAT_MALLOC_PADDING);
#else #else
parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
if (parser != NULL) { if (parser != NULL) {
@@ -1369,11 +1379,12 @@ parserCreate(const XML_Char *encodingName,
} else { } else {
XML_Memory_Handling_Suite *mtemp; XML_Memory_Handling_Suite *mtemp;
#if XML_GE == 1 #if XML_GE == 1
void *const sizeAndParser void *const sizeAndParser = malloc(sizeof(size_t) + EXPAT_MALLOC_PADDING
= malloc(sizeof(size_t) + sizeof(struct XML_ParserStruct)); + sizeof(struct XML_ParserStruct));
if (sizeAndParser != NULL) { if (sizeAndParser != NULL) {
*(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct); *(size_t *)sizeAndParser = sizeof(struct XML_ParserStruct);
parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)); parser = (XML_Parser)((char *)sizeAndParser + sizeof(size_t)
+ EXPAT_MALLOC_PADDING);
#else #else
parser = malloc(sizeof(struct XML_ParserStruct)); parser = malloc(sizeof(struct XML_ParserStruct));
if (parser != NULL) { if (parser != NULL) {
@@ -6437,6 +6448,10 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
// process its possible inner entities (which are added to the // process its possible inner entities (which are added to the
// m_openInternalEntities during doProlog or doContent calls above) // m_openInternalEntities during doProlog or doContent calls above)
entity->hasMore = XML_FALSE; entity->hasMore = XML_FALSE;
if (! entity->is_param
&& (openEntity->startTagLevel != parser->m_tagLevel)) {
return XML_ERROR_ASYNC_ENTITY;
}
triggerReenter(parser); triggerReenter(parser);
return result; return result;
} // End of entity processing, "if" block will return here } // End of entity processing, "if" block will return here
@@ -8135,7 +8150,7 @@ poolGrow(STRING_POOL *pool) {
if (bytesToAllocate == 0) if (bytesToAllocate == 0)
return XML_FALSE; return XML_FALSE;
temp = REALLOC(pool->parser, pool->blocks, (unsigned)bytesToAllocate); temp = REALLOC(pool->parser, pool->blocks, bytesToAllocate);
if (temp == NULL) if (temp == NULL)
return XML_FALSE; return XML_FALSE;
pool->blocks = temp; pool->blocks = temp;
+1 -1
View File
@@ -10,7 +10,7 @@
Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net> Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
Copyright (c) 2002 Karl Waclawek <karl@waclawek.net> Copyright (c) 2002 Karl Waclawek <karl@waclawek.net>
Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net> Copyright (c) 2002 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
Copyright (c) 2017-2024 Sebastian Pipping <sebastian@pipping.org> Copyright (c) 2017-2025 Sebastian Pipping <sebastian@pipping.org>
Licensed under the MIT license: Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
+33 -11
View File
@@ -2091,6 +2091,13 @@ START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) {
} }
END_TEST END_TEST
#if XML_GE == 1
static size_t
sizeRecordedFor(void *ptr) {
return *(size_t *)((char *)ptr - EXPAT_MALLOC_PADDING - sizeof(size_t));
}
#endif // XML_GE == 1
START_TEST(test_alloc_tracker_size_recorded) { START_TEST(test_alloc_tracker_size_recorded) {
XML_Memory_Handling_Suite memsuite = {malloc, realloc, free}; XML_Memory_Handling_Suite memsuite = {malloc, realloc, free};
@@ -2106,16 +2113,16 @@ START_TEST(test_alloc_tracker_size_recorded) {
void *ptr = expat_malloc(parser, 10, -1); void *ptr = expat_malloc(parser, 10, -1);
assert_true(ptr != NULL); assert_true(ptr != NULL);
assert_true(*((size_t *)ptr - 1) == 10); assert_true(sizeRecordedFor(ptr) == 10);
assert_true(expat_realloc(parser, ptr, SIZE_MAX / 2, -1) == NULL); assert_true(expat_realloc(parser, ptr, SIZE_MAX / 2, -1) == NULL);
assert_true(*((size_t *)ptr - 1) == 10); // i.e. unchanged assert_true(sizeRecordedFor(ptr) == 10); // i.e. unchanged
ptr = expat_realloc(parser, ptr, 20, -1); ptr = expat_realloc(parser, ptr, 20, -1);
assert_true(ptr != NULL); assert_true(ptr != NULL);
assert_true(*((size_t *)ptr - 1) == 20); assert_true(sizeRecordedFor(ptr) == 20);
expat_free(parser, ptr, -1); expat_free(parser, ptr, -1);
#endif #endif
@@ -2125,6 +2132,22 @@ START_TEST(test_alloc_tracker_size_recorded) {
} }
END_TEST END_TEST
START_TEST(test_alloc_tracker_pointer_alignment) {
XML_Parser parser = XML_ParserCreate(NULL);
#if XML_GE == 1
assert_true(sizeof(long long) >= sizeof(size_t)); // self-test
long long *const ptr
= (long long *)expat_malloc(parser, 4 * sizeof(long long), -1);
ptr[0] = 0LL;
ptr[1] = 1LL;
ptr[2] = 2LL;
ptr[3] = 3LL;
expat_free(parser, ptr, -1);
#endif
XML_ParserFree(parser);
}
END_TEST
START_TEST(test_alloc_tracker_maximum_amplification) { START_TEST(test_alloc_tracker_maximum_amplification) {
if (g_reparseDeferralEnabledDefault == XML_TRUE) { if (g_reparseDeferralEnabledDefault == XML_TRUE) {
return; return;
@@ -2355,14 +2378,13 @@ make_alloc_test_case(Suite *s) {
tcase_add_test__ifdef_xml_dtd( tcase_add_test__ifdef_xml_dtd(
tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail); tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_tracker_size_recorded); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_size_recorded);
tcase_add_test__ifdef_xml_dtd(tc_alloc, tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_pointer_alignment);
test_alloc_tracker_maximum_amplification); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_maximum_amplification);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_tracker_threshold); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_threshold);
tcase_add_test__ifdef_xml_dtd(tc_alloc, tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_getbuffer_unlimited);
test_alloc_tracker_getbuffer_unlimited); tcase_add_test__if_xml_ge(tc_alloc, test_alloc_tracker_api);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_tracker_api);
tcase_add_test(tc_alloc, test_mem_api_cycle); tcase_add_test(tc_alloc, test_mem_api_cycle);
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_mem_api_unlimited); tcase_add_test__if_xml_ge(tc_alloc, test_mem_api_unlimited);
} }
+95 -1
View File
@@ -211,7 +211,7 @@ START_TEST(test_misc_version) {
if (! versions_equal(&read_version, &parsed_version)) if (! versions_equal(&read_version, &parsed_version))
fail("Version mismatch"); fail("Version mismatch");
if (xcstrcmp(version_text, XCS("expat_2.7.2")) if (xcstrcmp(version_text, XCS("expat_2.7.3"))
!= 0) /* needs bump on releases */ != 0) /* needs bump on releases */
fail("XML_*_VERSION in expat.h out of sync?\n"); fail("XML_*_VERSION in expat.h out of sync?\n");
} }
@@ -679,6 +679,98 @@ START_TEST(test_misc_expected_event_ptr_issue_980) {
} }
END_TEST END_TEST
START_TEST(test_misc_sync_entity_tolerated) {
const char *const doc = "<!DOCTYPE t0 [\n"
" <!ENTITY a '<t1></t1>'>\n"
" <!ENTITY b '<t2>two</t2>'>\n"
" <!ENTITY c '<t3>three<t4>four</t4>three</t3>'>\n"
" <!ENTITY d '<t5>&b;</t5>'>\n"
"]>\n"
"<t0>&a;&b;&c;&d;</t0>\n";
XML_Parser parser = XML_ParserCreate(NULL);
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
/*isFinal=*/XML_TRUE)
== XML_STATUS_OK);
XML_ParserFree(parser);
}
END_TEST
START_TEST(test_misc_async_entity_rejected) {
struct test_case {
const char *doc;
enum XML_Status expectedStatusNoGE;
enum XML_Error expectedErrorNoGE;
XML_Size expectedErrorLine;
XML_Size expectedErrorColumn;
};
const struct test_case cases[] = {
// Opened by one entity, closed by another
{"<!DOCTYPE t0 [\n"
" <!ENTITY open '<t1>'>\n"
" <!ENTITY close '</t1>'>\n"
"]>\n"
"<t0>&open;&close;</t0>\n",
XML_STATUS_OK, XML_ERROR_NONE, 5, 4},
// Opened by tag, closed by entity (non-root case)
{"<!DOCTYPE t0 [\n"
" <!ENTITY g0 ''>\n"
" <!ENTITY g1 '&g0;</t1>'>\n"
"]>\n"
"<t0><t1>&g1;</t0>\n",
XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 8},
// Opened by tag, closed by entity (root case)
{"<!DOCTYPE t0 [\n"
" <!ENTITY g0 ''>\n"
" <!ENTITY g1 '&g0;</t0>'>\n"
"]>\n"
"<t0>&g1;\n",
XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS, 5, 4},
// Opened by entity, closed by tag <-- regression from 2.7.0
{"<!DOCTYPE t0 [\n"
" <!ENTITY g0 ''>\n"
" <!ENTITY g1 '<t1>&g0;'>\n"
"]>\n"
"<t0>&g1;</t1></t0>\n",
XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 4},
// Opened by tag, closed by entity; then the other way around
{"<!DOCTYPE t0 [\n"
" <!ENTITY open '<t1>'>\n"
" <!ENTITY close '</t1>'>\n"
"]>\n"
"<t0><t1>&close;&open;</t1></t0>\n",
XML_STATUS_OK, XML_ERROR_NONE, 5, 8},
};
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
const struct test_case testCase = cases[i];
set_subtest("cases[%d]", (int)i);
const char *const doc = testCase.doc;
#if XML_GE == 1
const enum XML_Status expectedStatus = XML_STATUS_ERROR;
const enum XML_Error expectedError = XML_ERROR_ASYNC_ENTITY;
#else
const enum XML_Status expectedStatus = testCase.expectedStatusNoGE;
const enum XML_Error expectedError = testCase.expectedErrorNoGE;
#endif
XML_Parser parser = XML_ParserCreate(NULL);
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
/*isFinal=*/XML_TRUE)
== expectedStatus);
assert_true(XML_GetErrorCode(parser) == expectedError);
#if XML_GE == 1
assert_true(XML_GetCurrentLineNumber(parser) == testCase.expectedErrorLine);
assert_true(XML_GetCurrentColumnNumber(parser)
== testCase.expectedErrorColumn);
#endif
XML_ParserFree(parser);
}
}
END_TEST
void void
make_miscellaneous_test_case(Suite *s) { make_miscellaneous_test_case(Suite *s) {
TCase *tc_misc = tcase_create("miscellaneous tests"); TCase *tc_misc = tcase_create("miscellaneous tests");
@@ -707,4 +799,6 @@ make_miscellaneous_test_case(Suite *s) {
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser); tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content); tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980); tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980);
tcase_add_test(tc_misc, test_misc_sync_entity_tolerated);
tcase_add_test(tc_misc, test_misc_async_entity_rejected);
} }
+2 -2
View File
@@ -96,8 +96,8 @@ reportError(XML_Parser parser, const XML_Char *filename) {
ftprintf(stdout, ftprintf(stdout,
T("%s") T(":%") T(XML_FMT_INT_MOD) T("u") T(":%") T("%s") T(":%") T(XML_FMT_INT_MOD) T("u") T(":%")
T(XML_FMT_INT_MOD) T("u") T(": %s\n"), T(XML_FMT_INT_MOD) T("u") T(": %s\n"),
filename, XML_GetErrorLineNumber(parser), filename, XML_GetCurrentLineNumber(parser),
XML_GetErrorColumnNumber(parser), message); XML_GetCurrentColumnNumber(parser), message);
else else
ftprintf(stderr, T("%s: (unknown message %u)\n"), filename, ftprintf(stderr, T("%s: (unknown message %u)\n"), filename,
(unsigned int)code); (unsigned int)code);
+3 -3
View File
@@ -89,7 +89,7 @@
#define PACKAGE_NAME "expat" #define PACKAGE_NAME "expat"
/* Define to the full name and version of this package. */ /* Define to the full name and version of this package. */
#define PACKAGE_STRING "expat 2.7.2" #define PACKAGE_STRING "expat 2.7.3"
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "expat" #define PACKAGE_TARNAME "expat"
@@ -98,7 +98,7 @@
#define PACKAGE_URL "" #define PACKAGE_URL ""
/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "2.7.2" #define PACKAGE_VERSION "2.7.3"
/* Define to 1 if all of the C89 standard headers exist (not just the ones /* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for required in a freestanding environment). This macro is provided for
@@ -106,7 +106,7 @@
#define STDC_HEADERS 1 #define STDC_HEADERS 1
/* Version number of package */ /* Version number of package */
#define VERSION "2.7.2" #define VERSION "2.7.3"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */ significant byte first (like Motorola and SPARC, unlike Intel). */
+2 -2
View File
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\"/ .\"/
.Dd April 7, 2025 .Dd September 28, 2025
.Dt LIBBSDXML 3 .Dt LIBBSDXML 3
.Os .Os
.Sh NAME .Sh NAME
@@ -34,7 +34,7 @@
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Nm .Nm
library is a verbatim copy of the eXpat XML library version 2.7.2. library is a verbatim copy of the eXpat XML library version 2.7.3.
.Pp .Pp
The The
.Nm .Nm