@crossbind/port-expat 2.0.0-beta.66 → 2.0.0-beta.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.mjs +6 -0
- package/package.json +1 -1
- package/patches/pr1431-parser-reset.patch +120 -0
package/build.mjs
CHANGED
|
@@ -2,6 +2,12 @@ export default {
|
|
|
2
2
|
sha256: '16afbb9cefead2aa278105cf27d9f597bde7fbf3dbb85015857ca7ca6a4e89ba', // expat-2.9.0.tar.gz
|
|
3
3
|
getURL: (version) => `https://github.com/libexpat/libexpat/releases/download/R_${version.replaceAll('.', '_')}/expat-${version}.tar.gz`,
|
|
4
4
|
buildType: 'cmake',
|
|
5
|
+
patches: [
|
|
6
|
+
{
|
|
7
|
+
file: new URL('./patches/pr1431-parser-reset.patch', import.meta.url),
|
|
8
|
+
advisories: ['CVE-2026-113351'],
|
|
9
|
+
},
|
|
10
|
+
],
|
|
5
11
|
getBuildParams: () => [
|
|
6
12
|
'-DEXPAT_BUILD_TESTS=OFF',
|
|
7
13
|
'-DEXPAT_BUILD_TOOLS=OFF',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crossbind/port-expat",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.67",
|
|
4
4
|
"nativeVersion": "2.9.0",
|
|
5
5
|
"description": "This package provides the precompiled Expat XML parser library, built using crossbind, for seamless integration into JavaScript, WebAssembly, and React Native projects. It enables fast and efficient parsing of XML data, making it ideal for applications requiring robust XML handling across platforms. Perfect for web, server-side, and mobile development environments.",
|
|
6
6
|
"homepage": "https://crossbind.dev/ports/expat/",
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
[CVE-2026-113351] Fix parser reset
|
|
2
|
+
Upstream: https://github.com/libexpat/libexpat/pull/1431 (lib/xmlparse.c only, without the repository's expat/ prefix)
|
|
3
|
+
|
|
4
|
+
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
|
|
5
|
+
index ab2d4f1ed2..f12b7d31ad 100644
|
|
6
|
+
--- a/lib/xmlparse.c
|
|
7
|
+
+++ b/lib/xmlparse.c
|
|
8
|
+
@@ -467,6 +467,7 @@ typedef struct accounting {
|
|
9
|
+
typedef struct MALLOC_TRACKER {
|
|
10
|
+
size_t bytesAllocated;
|
|
11
|
+
size_t peakBytesAllocated; // updated live only for debug level >=2
|
|
12
|
+
+ size_t bytesAllocatedWhenLastReset;
|
|
13
|
+
unsigned long debugLevel;
|
|
14
|
+
float maximumAmplificationFactor; // >=1.0
|
|
15
|
+
XmlBigCount activationThresholdBytes;
|
|
16
|
+
@@ -615,7 +616,8 @@ static XML_Parser parserCreate(const XML_Char *encodingName,
|
|
17
|
+
const XML_Char *nameSep, DTD *dtd,
|
|
18
|
+
XML_Parser parentParser);
|
|
19
|
+
|
|
20
|
+
-static void parserInit(XML_Parser parser, const XML_Char *encodingName);
|
|
21
|
+
+static void parserInit(XML_Parser parser, const XML_Char *encodingName,
|
|
22
|
+
+ bool isReset);
|
|
23
|
+
|
|
24
|
+
#if XML_GE == 1
|
|
25
|
+
static float accountingGetCurrentAmplification(XML_Parser rootParser);
|
|
26
|
+
@@ -865,11 +867,22 @@ expat_heap_increase_tolerable(XML_Parser rootParser, size_t increase,
|
|
27
|
+
size_t newTotal = 0;
|
|
28
|
+
bool tolerable = true;
|
|
29
|
+
|
|
30
|
+
+ // The idea is to subtract the amount of memory that was already
|
|
31
|
+
+ // allocated the last time that `XML_ParserReset` was called for
|
|
32
|
+
+ // this parser, the memory use of one document could skew the
|
|
33
|
+
+ // memory statso of the next document.
|
|
34
|
+
+ const size_t bytesAllocated
|
|
35
|
+
+ = (rootParser->m_alloc_tracker.bytesAllocatedWhenLastReset
|
|
36
|
+
+ > rootParser->m_alloc_tracker.bytesAllocated)
|
|
37
|
+
+ ? 0
|
|
38
|
+
+ : (rootParser->m_alloc_tracker.bytesAllocated
|
|
39
|
+
+ - rootParser->m_alloc_tracker.bytesAllocatedWhenLastReset);
|
|
40
|
+
+
|
|
41
|
+
// Detect integer overflow
|
|
42
|
+
- if (SIZE_MAX - rootParser->m_alloc_tracker.bytesAllocated < increase) {
|
|
43
|
+
+ if (SIZE_MAX - bytesAllocated < increase) {
|
|
44
|
+
tolerable = false;
|
|
45
|
+
} else {
|
|
46
|
+
- newTotal = rootParser->m_alloc_tracker.bytesAllocated + increase;
|
|
47
|
+
+ newTotal = bytesAllocated + increase;
|
|
48
|
+
|
|
49
|
+
if (newTotal >= rootParser->m_alloc_tracker.activationThresholdBytes) {
|
|
50
|
+
assert(newTotal > 0);
|
|
51
|
+
@@ -1449,7 +1462,7 @@ parserCreate(const XML_Char *encodingName,
|
|
52
|
+
|
|
53
|
+
poolInit(&parser->m_tempPool, parser);
|
|
54
|
+
poolInit(&parser->m_temp2Pool, parser);
|
|
55
|
+
- parserInit(parser, encodingName);
|
|
56
|
+
+ parserInit(parser, encodingName, /*isReset=*/false);
|
|
57
|
+
|
|
58
|
+
if (encodingName && ! parser->m_protocolEncodingName) {
|
|
59
|
+
if (dtd) {
|
|
60
|
+
@@ -1476,7 +1489,7 @@ parserCreate(const XML_Char *encodingName,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static void
|
|
64
|
+
-parserInit(XML_Parser parser, const XML_Char *encodingName) {
|
|
65
|
+
+parserInit(XML_Parser parser, const XML_Char *encodingName, bool isReset) {
|
|
66
|
+
parser->m_processor = prologInitProcessor;
|
|
67
|
+
XmlPrologStateInit(&parser->m_prologState);
|
|
68
|
+
if (encodingName != NULL) {
|
|
69
|
+
@@ -1557,15 +1570,24 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
|
|
70
|
+
parser->m_hash_secret_salt_set = XML_FALSE;
|
|
71
|
+
|
|
72
|
+
#if XML_GE == 1
|
|
73
|
+
- memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
|
|
74
|
+
- parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
|
|
75
|
+
- parser->m_accounting.maximumAmplificationFactor
|
|
76
|
+
- = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT;
|
|
77
|
+
- parser->m_accounting.activationThresholdBytes
|
|
78
|
+
- = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT;
|
|
79
|
+
-
|
|
80
|
+
- memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS));
|
|
81
|
+
- parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
|
|
82
|
+
+ parser->m_accounting.countBytesDirect = 0;
|
|
83
|
+
+ parser->m_accounting.countBytesIndirect = 0;
|
|
84
|
+
+ if (! isReset) {
|
|
85
|
+
+ parser->m_accounting.debugLevel
|
|
86
|
+
+ = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
|
|
87
|
+
+ parser->m_accounting.maximumAmplificationFactor
|
|
88
|
+
+ = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT;
|
|
89
|
+
+ parser->m_accounting.activationThresholdBytes
|
|
90
|
+
+ = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT;
|
|
91
|
+
+ }
|
|
92
|
+
+
|
|
93
|
+
+ parser->m_entity_stats.countEverOpened = 0;
|
|
94
|
+
+ parser->m_entity_stats.currentDepth = 0;
|
|
95
|
+
+ parser->m_entity_stats.maximumDepthSeen = 0;
|
|
96
|
+
+ if (! isReset)
|
|
97
|
+
+ parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
|
|
98
|
+
+#else
|
|
99
|
+
+ UNUSED_P(isReset);
|
|
100
|
+
#endif
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@@ -1628,8 +1650,16 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
|
|
104
|
+
poolClear(&parser->m_temp2Pool);
|
|
105
|
+
FREE(parser, (void *)parser->m_protocolEncodingName);
|
|
106
|
+
parser->m_protocolEncodingName = NULL;
|
|
107
|
+
- parserInit(parser, encodingName);
|
|
108
|
+
+ parserInit(parser, encodingName, /*isReset=*/true);
|
|
109
|
+
dtdReset(parser->m_dtd, parser);
|
|
110
|
+
+
|
|
111
|
+
+#if XML_GE == 1
|
|
112
|
+
+ parser->m_alloc_tracker.bytesAllocatedWhenLastReset
|
|
113
|
+
+ = parser->m_alloc_tracker.bytesAllocated;
|
|
114
|
+
+#endif
|
|
115
|
+
+
|
|
116
|
+
+ // NOTE: This effectively checks for `copyString` having failed during the
|
|
117
|
+
+ // call to `parserInit` above
|
|
118
|
+
if (encodingName && ! parser->m_protocolEncodingName) {
|
|
119
|
+
parser->m_errorCode = XML_ERROR_NO_MEMORY;
|
|
120
|
+
return XML_FALSE;
|