1
0
mirror of https://git.yoctoproject.org/poky synced 2026-07-27 07:27:12 +00:00

expat: patch CVE-2026-41080

Pick github PR [1] mentioned in [2].
* 969af8f4654ce50d837bb9199a73d1d02d2c7e16..4ba09dc471b39a78d77e5179d0243186c0c4ff7a
* dropped code which doesn't exist in 2.6.4 yet (github actions, map
  file)
* resolved minor conflicts (formatting)
* picked 2 additional commits to apply the code cleanly

[1] https://github.com/libexpat/libexpat/pull/1183
[2] https://security-tracker.debian.org/tracker/CVE-2026-41080

(From OE-Core rev: 273968c71fbf4a376996df555a8283bf63674ae8)

Signed-off-by: Peter Marko <peter.marko@siemens.com>
[YC: See discussion :
https://lore.kernel.org/openembedded-core/2030b4435c8bc81bb4452637c0517ac33ab94d20.camel@pbarker.dev/T/#m56c5da4033c2f3571027c2745431178064ea1b5d ]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
Peter Marko
2026-05-05 22:52:28 +02:00
committed by Paul Barker
parent 9c72283ec8
commit c5f228145b
4 changed files with 549 additions and 0 deletions
@@ -0,0 +1,50 @@
From fe04a7f0ff8afe57ba33d919f368b1ba23bcda92 Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Sun, 30 Mar 2025 19:26:55 +0200
Subject: [PATCH 1/3] lib/xmlparse.c: Address clang-tidy warning
misc-no-recursion
CVE: CVE-2026-41080
Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/fe04a7f0ff8afe57ba33d919f368b1ba23bcda92]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
lib/xmlparse.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 9bc67f38..cb25c37b 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -1243,9 +1243,10 @@ generate_hash_secret_salt(XML_Parser parser) {
static unsigned long
get_hash_secret_salt(XML_Parser parser) {
- if (parser->m_parentParser != NULL)
- return get_hash_secret_salt(parser->m_parentParser);
- return parser->m_hash_secret_salt;
+ const XML_Parser rootParser = getRootParserOf(parser, NULL);
+ assert(! rootParser->m_parentParser);
+
+ return rootParser->m_hash_secret_salt;
}
static enum XML_Error
@@ -2321,12 +2322,14 @@ int XMLCALL
XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
if (parser == NULL)
return 0;
- if (parser->m_parentParser)
- return XML_SetHashSalt(parser->m_parentParser, hash_salt);
+
+ const XML_Parser rootParser = getRootParserOf(parser, NULL);
+ assert(! rootParser->m_parentParser);
+
/* block after XML_Parse()/XML_ParseBuffer() has been called */
- if (parserBusy(parser))
+ if (parserBusy(rootParser))
return 0;
- parser->m_hash_secret_salt = hash_salt;
+ rootParser->m_hash_secret_salt = hash_salt;
return 1;
}
@@ -0,0 +1,29 @@
From 7fb2c7a454edc9e2880073a27f899c31d9b078ce Mon Sep 17 00:00:00 2001
From: Atrem Borovik <polzovatellllk@gmail.com>
Date: Sat, 20 Dec 2025 13:22:16 +0300
Subject: [PATCH 2/3] WASI: remove getpid
CVE: CVE-2026-41080
Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/7fb2c7a454edc9e2880073a27f899c31d9b078ce]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
lib/xmlparse.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index cb25c37b..1bafb948 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -1228,8 +1228,11 @@ generate_hash_secret_salt(XML_Parser parser) {
# endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
/* .. and self-made low quality for backup: */
+ entropy = gather_time_entropy();
+# if ! defined(__wasi__)
/* Process ID is 0 bits entropy if attacker has local access */
- entropy = gather_time_entropy() ^ getpid();
+ entropy ^= getpid();
+# endif
/* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
if (sizeof(unsigned long) == 4) {
@@ -0,0 +1,467 @@
From b77ab600e1893fdcfc3868d0a46efcc87c87943d Mon Sep 17 00:00:00 2001
From: Sebastian Pipping <sebastian@pipping.org>
Date: Wed, 8 Apr 2026 15:41:54 +0200
Subject: [PATCH 3/3] [CVE-2026-41080] Improve protection against hash flooding
(fixes #47)
Fixes #47
CVE: CVE-2026-41080
Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1183]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
Changes | 16 ++++++
doc/reference.html | 51 ++++++++++++++--
lib/expat.h | 12 ++++
lib/internal.h | 2 +
lib/xmlparse.c | 118 ++++++++++++++++++++++++++------------
tests/basic_tests.c | 25 ++++++++
6 files changed, 181 insertions(+), 43 deletions(-)
diff --git a/Changes b/Changes
index 4265d608..1d87d6a0 100644
--- a/Changes
+++ b/Changes
@@ -30,6 +30,22 @@
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Patches:
+ Security fixes:
+ #47 #1183 CVE-2026-41080 -- The existing hash flooding protection
+ (based on SipHash) only used 4 to 8 bytes of entropy for
+ a salt, when 16 bytes of salt are supported by the
+ implementation of SipHash used by Expat. Now full 16 bytes
+ of entropy are used to improve protection against hash
+ flooding attacks.
+ Existing API function XML_SetHashSalt is now deprecated
+ because of its limitations, and its use should be
+ considered a vulnerability. Please either use the new API
+ function XML_SetHashSalt16Bytes (with known-high-quality
+ entropy input only!) instead, or leave the derivation of
+ a 16-bytes hash salt from high quality entropy to Expat's
+ internal machinery (by *not* calling either of the two
+ XML_SetHashSalt* functions).
+
Security fixes:
#1018 #1034 CVE-2025-59375 -- Disallow use of disproportional amounts of
dynamic memory from within an Expat parser (e.g. previously
diff --git a/doc/reference.html b/doc/reference.html
index 8f14b011..7f374f84 100644
--- a/doc/reference.html
+++ b/doc/reference.html
@@ -174,7 +174,8 @@ interface.</p>
<li><a href="#XML_GetAttributeInfo">XML_GetAttributeInfo</a></li>
<li><a href="#XML_SetEncoding">XML_SetEncoding</a></li>
<li><a href="#XML_SetParamEntityParsing">XML_SetParamEntityParsing</a></li>
- <li><a href="#XML_SetHashSalt">XML_SetHashSalt</a></li>
+ <li><a href="#XML_SetHashSalt">XML_SetHashSalt</a> (deprecated)</li>
+ <li><a href="#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></li>
<li><a href="#XML_UseForeignDTD">XML_UseForeignDTD</a></li>
<li><a href="#XML_SetReturnNSTriplet">XML_SetReturnNSTriplet</a></li>
<li><a href="#XML_DefaultCurrent">XML_DefaultCurrent</a></li>
@@ -2553,10 +2554,10 @@ The choices for <code>code</code> are:
no effect and will always return 0.
</div>
-<h4 id="XML_SetHashSalt">XML_SetHashSalt</h4>
+<h4 id="XML_SetHashSalt">XML_SetHashSalt (deprecated)</h4>
<pre class="fcndec">
int XMLCALL
-XML_SetHashSalt(XML_Parser p,
+XML_SetHashSalt(XML_Parser parser,
unsigned long hash_salt);
</pre>
<div class="fcndef">
@@ -2564,15 +2565,55 @@ Sets the hash salt to use for internal hash calculations.
Helps in preventing DoS attacks based on predicting hash
function behavior. In order to have an effect this must be called
before parsing has started. Returns 1 if successful, 0 when called
-after <code>XML_Parse</code> or <code>XML_ParseBuffer</code>.
+after <code>XML_Parse</code> or <code>XML_ParseBuffer</code> or when
+ <code>parser</code> is <code>NULL</code>.
+ <p>
+ <b>Note:</b> Function <code>XML_SetHashSalt</code> is
+ <strong>deprecated</strong>. Please use function <code><a href=
+ "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code> instead for better
+ security. <code>XML_SetHashSalt</code> only provides 4 to 8 bytes of entropy
+ (depending on the size of type <code>unsigned long</code>) while the SipHash
+ implementation used by Expat can leverage up to 16 bytes of entropy — at least
+ twice as much. Function <code><a href=
+ "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code> of Expat &gt;=2.7.6
+ (and where backported) matches the amount of entropy supported by SipHash.
+ </p>.
<p><b>Note:</b> This call is optional, as the parser will auto-generate
-a new random salt value if no value has been set at the start of parsing.</p>
+a new random salt value internally if no value has been set by the start of parsing.</p>
<p><b>Note:</b> One should not call <code>XML_SetHashSalt</code> with a
hash salt value of 0, as this value is used as sentinel value to indicate
that <code>XML_SetHashSalt</code> has <b>not</b> been called. Consequently
such a call will have no effect, even if it returns 1.</p>
</div>
+ <h4 id="XML_SetHashSalt16Bytes">
+ XML_SetHashSalt16Bytes
+ </h4>
+
+ <pre class="fcndec">
+/* Added in Expat 2.7.6. */
+XML_Bool XMLCALL
+XML_SetHashSalt16Bytes(XML_Parser parser,
+ const uint8_t entropy[16]);
+</pre>
+ <div class="fcndef">
+ Sets the hash salt to use for internal hash calculations. Helps in preventing DoS
+ attacks based on predicting hash function behavior. In order to have an effect
+ this must be called before parsing has started. Returns <code>XML_TRUE</code> if
+ successful, <code>XML_FALSE</code> when called after <code>XML_Parse</code> or
+ <code>XML_ParseBuffer</code> or when <code>parser</code> is <code>NULL</code>.
+ <p>
+ <b>Note:</b> Setting a salt that is <em>not</em> from a source of high quality
+ entropy (like <code>getentropy(3)</code>) will make the parser vulnerable to
+ hash flooding attacks.
+ </p>
+
+ <p>
+ <b>Note:</b> This call is optional, as the parser will auto-generate a new
+ random salt value internally if no value has been set by the start of parsing.
+ </p>
+ </div>
+
<h4 id="XML_UseForeignDTD">XML_UseForeignDTD</h4>
<pre class="fcndec">
enum XML_Error XMLCALL
diff --git a/lib/expat.h b/lib/expat.h
index df207e9e..b356e002 100644
--- a/lib/expat.h
+++ b/lib/expat.h
@@ -44,6 +44,7 @@
#ifndef Expat_INCLUDED
#define Expat_INCLUDED 1
+# include <stdint.h> // for uint8_t
#include <stdlib.h>
#include "expat_external.h"
@@ -916,10 +917,21 @@ XML_SetParamEntityParsing(XML_Parser parser,
function behavior. This must be called before parsing is started.
Returns 1 if successful, 0 when called after parsing has started.
Note: If parser == NULL, the function will do nothing and return 0.
+ DEPRECATED since Expat 2.7.6.
*/
XMLPARSEAPI(int)
XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt);
+/* Sets the hash salt to use for internal hash calculations.
+ Helps in preventing DoS attacks based on predicting hash function behavior.
+ This must be called before parsing is started.
+ Returns XML_TRUE if successful, XML_FALSE when called after parsing has
+ started or when parser is NULL.
+ Added in Expat 2.7.6.
+*/
+XMLPARSEAPI(XML_Bool)
+XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]);
+
/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
XML_GetErrorCode returns information about the error.
*/
diff --git a/lib/internal.h b/lib/internal.h
index 32faaa05..617d6454 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -113,6 +113,7 @@
#if defined(_WIN32) \
&& (! defined(__USE_MINGW_ANSI_STDIO) \
|| (1 - __USE_MINGW_ANSI_STDIO - 1 == 0))
+# define EXPAT_FMT_LLX(midpart) "%" midpart "I64x"
# define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
# if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
@@ -122,6 +123,7 @@
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
# endif
#else
+# define EXPAT_FMT_LLX(midpart) "%" midpart "llx"
# define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
# if ! defined(ULONG_MAX)
# error Compiler did not define ULONG_MAX for us
diff --git a/lib/xmlparse.c b/lib/xmlparse.c
index 1bafb948..75a7e5d0 100644
--- a/lib/xmlparse.c
+++ b/lib/xmlparse.c
@@ -604,7 +604,7 @@ static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
static XML_Char *copyString(const XML_Char *s, XML_Parser parser);
-static unsigned long generate_hash_secret_salt(XML_Parser parser);
+static struct sipkey generate_hash_secret_salt(void);
static XML_Bool startParsing(XML_Parser parser);
static XML_Parser parserCreate(const XML_Char *encodingName,
@@ -777,7 +777,8 @@ struct XML_ParserStruct {
XML_Bool m_useForeignDTD;
enum XML_ParamEntityParsing m_paramEntityParsing;
#endif
- unsigned long m_hash_secret_salt;
+ struct sipkey m_hash_secret_salt_128;
+ XML_Bool m_hash_secret_salt_set;
#if XML_GE == 1
ACCOUNTING m_accounting;
MALLOC_TRACKER m_alloc_tracker;
@@ -1189,69 +1190,65 @@ gather_time_entropy(void) {
#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
-static unsigned long
-ENTROPY_DEBUG(const char *label, unsigned long entropy) {
+static struct sipkey
+ENTROPY_DEBUG(const char *label, struct sipkey entropy_128) {
if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) {
- fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
- (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
+ fprintf(stderr,
+ "expat: Entropy: %s --> [0x" EXPAT_FMT_LLX(
+ "016") ", 0x" EXPAT_FMT_LLX("016") "] (16 bytes)\n",
+ label, (unsigned long long)entropy_128.k[0],
+ (unsigned long long)entropy_128.k[1]);
}
- return entropy;
+ return entropy_128;
}
-static unsigned long
-generate_hash_secret_salt(XML_Parser parser) {
- unsigned long entropy;
- (void)parser;
+static struct sipkey
+generate_hash_secret_salt(void) {
+ struct sipkey entropy;
/* "Failproof" high quality providers: */
#if defined(HAVE_ARC4RANDOM_BUF)
arc4random_buf(&entropy, sizeof(entropy));
return ENTROPY_DEBUG("arc4random_buf", entropy);
#elif defined(HAVE_ARC4RANDOM)
- writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
+ writeRandomBytes_arc4random(&entropy, sizeof(entropy));
return ENTROPY_DEBUG("arc4random", entropy);
#else
/* Try high quality providers first .. */
# ifdef _WIN32
- if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
+ if (writeRandomBytes_rand_s(&entropy, sizeof(entropy))) {
return ENTROPY_DEBUG("rand_s", entropy);
}
# elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
- if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
+ if (writeRandomBytes_getrandom_nonblock(&entropy, sizeof(entropy))) {
return ENTROPY_DEBUG("getrandom", entropy);
}
# endif
# if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
- if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
+ if (writeRandomBytes_dev_urandom(&entropy, sizeof(entropy))) {
return ENTROPY_DEBUG("/dev/urandom", entropy);
}
# endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
/* .. and self-made low quality for backup: */
- entropy = gather_time_entropy();
+ entropy.k[0] = 0;
+ entropy.k[1] = gather_time_entropy();
# if ! defined(__wasi__)
/* Process ID is 0 bits entropy if attacker has local access */
- entropy ^= getpid();
+ entropy.k[1] ^= getpid();
# endif
/* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
if (sizeof(unsigned long) == 4) {
- return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
+ entropy.k[1] *= 2147483647;
+ return ENTROPY_DEBUG("fallback(4)", entropy);
} else {
- return ENTROPY_DEBUG("fallback(8)",
- entropy * (unsigned long)2305843009213693951ULL);
+ entropy.k[1] *= 2305843009213693951ULL;
+ return ENTROPY_DEBUG("fallback(8)", entropy);
}
#endif
}
-static unsigned long
-get_hash_secret_salt(XML_Parser parser) {
- const XML_Parser rootParser = getRootParserOf(parser, NULL);
- assert(! rootParser->m_parentParser);
-
- return rootParser->m_hash_secret_salt;
-}
-
static enum XML_Error
callProcessor(XML_Parser parser, const char *start, const char *end,
const char **endPtr) {
@@ -1320,8 +1316,10 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
static XML_Bool /* only valid for root parser */
startParsing(XML_Parser parser) {
/* hash functions must be initialized before setContext() is called */
- if (parser->m_hash_secret_salt == 0)
- parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
+ if (parser->m_hash_secret_salt_set != XML_TRUE) {
+ parser->m_hash_secret_salt_128 = generate_hash_secret_salt();
+ parser->m_hash_secret_salt_set = XML_TRUE;
+ }
if (parser->m_ns) {
/* implicit context only set for root parser, since child
parsers (i.e. external entity parsers) will inherit it
@@ -1609,7 +1607,9 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_useForeignDTD = XML_FALSE;
parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
#endif
- parser->m_hash_secret_salt = 0;
+ parser->m_hash_secret_salt_128.k[0] = 0;
+ parser->m_hash_secret_salt_128.k[1] = 0;
+ parser->m_hash_secret_salt_set = XML_FALSE;
#if XML_GE == 1
memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
@@ -1776,7 +1776,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
from hash tables associated with either parser without us having
to worry which hash secrets each table has.
*/
- unsigned long oldhash_secret_salt;
+ struct sipkey oldhash_secret_salt_128;
+ XML_Bool oldhash_secret_salt_set;
XML_Bool oldReparseDeferralEnabled;
/* Validate the oldParser parameter before we pull everything out of it */
@@ -1822,7 +1823,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
from hash tables associated with either parser without us having
to worry which hash secrets each table has.
*/
- oldhash_secret_salt = parser->m_hash_secret_salt;
+ oldhash_secret_salt_128 = parser->m_hash_secret_salt_128;
+ oldhash_secret_salt_set = parser->m_hash_secret_salt_set;
oldReparseDeferralEnabled = parser->m_reparseDeferralEnabled;
#ifdef XML_DTD
@@ -1877,7 +1879,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
parser->m_ns_triplets = oldns_triplets;
- parser->m_hash_secret_salt = oldhash_secret_salt;
+ parser->m_hash_secret_salt_128 = oldhash_secret_salt_128;
+ parser->m_hash_secret_salt_set = oldhash_secret_salt_set;
parser->m_reparseDeferralEnabled = oldReparseDeferralEnabled;
parser->m_parentParser = oldParser;
#ifdef XML_DTD
@@ -2321,6 +2324,7 @@ XML_SetParamEntityParsing(XML_Parser parser,
#endif
}
+// DEPRECATED since Expat 2.7.6.
int XMLCALL
XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
if (parser == NULL)
@@ -2332,10 +2336,46 @@ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (parserBusy(rootParser))
return 0;
- rootParser->m_hash_secret_salt = hash_salt;
+
+ rootParser->m_hash_secret_salt_128.k[0] = 0;
+ rootParser->m_hash_secret_salt_128.k[1] = hash_salt;
+
+ if (hash_salt != 0) { // to remain backwards compatible
+ rootParser->m_hash_secret_salt_set = XML_TRUE;
+
+ if (sizeof(unsigned long) == 4)
+ ENTROPY_DEBUG("explicit(4)", rootParser->m_hash_secret_salt_128);
+ else
+ ENTROPY_DEBUG("explicit(8)", rootParser->m_hash_secret_salt_128);
+ }
+
return 1;
}
+XML_Bool XMLCALL
+XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]) {
+ if (parser == NULL)
+ return XML_FALSE;
+
+ if (entropy == NULL)
+ return XML_FALSE;
+
+ const XML_Parser rootParser = getRootParserOf(parser, NULL);
+ assert(! rootParser->m_parentParser);
+
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (parserBusy(rootParser))
+ return XML_FALSE;
+
+ sip_tokey(&(rootParser->m_hash_secret_salt_128), entropy);
+
+ rootParser->m_hash_secret_salt_set = XML_TRUE;
+
+ ENTROPY_DEBUG("explicit(16)", rootParser->m_hash_secret_salt_128);
+
+ return XML_TRUE;
+}
+
enum XML_Status XMLCALL
XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
@@ -7837,8 +7877,10 @@ keylen(KEY s) {
static void
copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
- key->k[0] = 0;
- key->k[1] = get_hash_secret_salt(parser);
+ const XML_Parser rootParser = getRootParserOf(parser, NULL);
+ assert(! rootParser->m_parentParser);
+
+ *key = rootParser->m_hash_secret_salt_128;
}
static unsigned long FASTCALL
diff --git a/tests/basic_tests.c b/tests/basic_tests.c
index 023d9ce4..380caf19 100644
--- a/tests/basic_tests.c
+++ b/tests/basic_tests.c
@@ -204,6 +204,30 @@ START_TEST(test_hash_collision) {
END_TEST
#undef COLLIDING_HASH_SALT
+START_TEST(test_hash_salt_setter) {
+ const uint8_t entropy[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ XML_Parser parser = XML_ParserCreate(NULL);
+
+ // NULL parser should be rejected
+ assert_true(XML_SetHashSalt16Bytes(NULL, entropy) == XML_FALSE);
+
+ // NULL entropy should be rejected
+ assert_true(XML_SetHashSalt16Bytes(parser, NULL) == XML_FALSE);
+
+ // Setting should be allowed more than once
+ assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_TRUE);
+ assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_TRUE);
+
+ // But not after parsing has started
+ assert_true(XML_Parse(parser, "", 0, XML_FALSE /* isFinal */)
+ == XML_STATUS_OK);
+ assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_FALSE);
+
+ XML_ParserFree(parser);
+}
+END_TEST
+
/* Regression test for SF bug #491986. */
START_TEST(test_danish_latin1) {
const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
@@ -6244,6 +6268,7 @@ make_basic_test_case(Suite *s) {
tcase_add_test(tc_basic, test_bom_utf16_le);
tcase_add_test(tc_basic, test_nobom_utf16_le);
tcase_add_test(tc_basic, test_hash_collision);
+ tcase_add_test(tc_basic, test_hash_salt_setter);
tcase_add_test(tc_basic, test_illegal_utf8);
tcase_add_test(tc_basic, test_utf8_auto_align);
tcase_add_test(tc_basic, test_utf16);
+3
View File
@@ -51,6 +51,9 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \
file://CVE-2026-32777-02.patch \
file://CVE-2026-32778-01.patch \
file://CVE-2026-32778-02.patch \
file://CVE-2026-41080-01.patch \
file://CVE-2026-41080-02.patch \
file://CVE-2026-41080-03.patch \
"
GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"