++ Large tokens may require many parse calls before enough data is available for Expat to parse it in full.
++ If Expat retried parsing the token on every parse call, parsing could take quadratic time.
++ To avoid this, Expat only retries once a significant amount of new data is available.
++ This function allows disabling this behavior.
++
++
++ The enabled argument should be XML_TRUE or XML_FALSE.
++
++
++ Returns XML_TRUE on success, and XML_FALSE on error.
++
The functions in this section either obtain state information from
+diff --git a/lib/expat.h b/lib/expat.h
+index 9e64174..73dda6d 100644
+--- a/lib/expat.h
++++ b/lib/expat.h
+@@ -16,6 +16,7 @@
+ Copyright (c) 2016 Thomas Beutlich
+ Copyright (c) 2017 Rhodri James
+ Copyright (c) 2022 Thijs Schreijer
++ Copyright (c) 2023 Sony Corporation / Snild Dolkow
+ Licensed under the MIT license:
+
+ Permission is hereby granted, free of charge, to any person obtaining
+@@ -1054,6 +1055,10 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold(
+ XML_Parser parser, unsigned long long activationThresholdBytes);
+ #endif
+
++/* Added in Expat 2.6.0. */
++XMLPARSEAPI(XML_Bool)
++XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
++
+ /* Expat follows the semantic versioning convention.
+ See http://semver.org.
+ */
+diff --git a/lib/libexpat.def.cmake b/lib/libexpat.def.cmake
+index 61a4f00..10ee9cd 100644
+--- a/lib/libexpat.def.cmake
++++ b/lib/libexpat.def.cmake
+@@ -77,3 +77,5 @@ EXPORTS
+ ; added with version 2.4.0
+ @_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionActivationThreshold @69
+ @_EXPAT_COMMENT_DTD_OR_GE@ XML_SetBillionLaughsAttackProtectionMaximumAmplification @70
++; added with version 2.6.0
++ XML_SetReparseDeferralEnabled @71
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index be6dd92..8cf32e0 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -633,6 +633,7 @@ struct XML_ParserStruct {
+ XML_Index m_parseEndByteIndex;
+ const char *m_parseEndPtr;
+ size_t m_partialTokenBytesBefore; /* used in heuristic to avoid O(n^2) */
++ XML_Bool m_reparseDeferralEnabled;
+ XML_Char *m_dataBuf;
+ XML_Char *m_dataBufEnd;
+ XML_StartElementHandler m_startElementHandler;
+@@ -969,7 +970,7 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
+ const char **endPtr) {
+ const size_t have_now = EXPAT_SAFE_PTR_DIFF(end, start);
+
+- if (g_reparseDeferralEnabledDefault
++ if (parser->m_reparseDeferralEnabled
+ && ! parser->m_parsingStatus.finalBuffer) {
+ // Heuristic: don't try to parse a partial token again until the amount of
+ // available data has increased significantly.
+@@ -1175,6 +1176,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
+ parser->m_parseEndByteIndex = 0;
+ parser->m_parseEndPtr = NULL;
+ parser->m_partialTokenBytesBefore = 0;
++ parser->m_reparseDeferralEnabled = g_reparseDeferralEnabledDefault;
+ parser->m_declElementType = NULL;
+ parser->m_declAttributeId = NULL;
+ parser->m_declEntity = NULL;
+@@ -2601,6 +2603,15 @@ XML_SetBillionLaughsAttackProtectionActivationThreshold(
+ }
+ #endif /* XML_GE == 1 */
+
++XML_Bool XMLCALL
++XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled) {
++ if (parser != NULL && (enabled == XML_TRUE || enabled == XML_FALSE)) {
++ parser->m_reparseDeferralEnabled = enabled;
++ return XML_TRUE;
++ }
++ return XML_FALSE;
++}
++
+ /* Initially tag->rawName always points into the parse buffer;
+ for those TAG instances opened while the current parse buffer was
+ processed, and not yet closed, we need to store tag->rawName in a more
+--
+2.40.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2023-52425-0008.patch b/meta/recipes-core/expat/expat/CVE-2023-52425-0008.patch
new file mode 100644
index 0000000000..fa25fcd2db
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2023-52425-0008.patch
@@ -0,0 +1,95 @@
+From 8ddd8e86aa446d02eb8d398972d3b10d4cad908a Mon Sep 17 00:00:00 2001
+From: Snild Dolkow
+Date: Fri, 29 Sep 2023 10:14:59 +0200
+Subject: [PATCH] Try to parse even when incoming len is zero
+
+If the reparse deferral setting has changed, it may be possible to
+finish a token.
+
+CVE: CVE-2023-52425
+
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/8ddd8e86aa446d02eb8d398972d3b10d4cad908a]
+
+Signed-off-by: Meenali Gupta
+---
+ lib/xmlparse.c | 55 ++++++++------------------------------------------
+ 1 file changed, 8 insertions(+), 47 deletions(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 8cf32e0..f4ff66e 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -1896,46 +1896,8 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
+ parser->m_parsingStatus.parsing = XML_PARSING;
+ }
+
+- if (len == 0) {
+- parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
+- if (! isFinal)
+- return XML_STATUS_OK;
+- parser->m_positionPtr = parser->m_bufferPtr;
+- parser->m_parseEndPtr = parser->m_bufferEnd;
+-
+- /* If data are left over from last buffer, and we now know that these
+- data are the final chunk of input, then we have to check them again
+- to detect errors based on that fact.
+- */
+- parser->m_errorCode
+- = callProcessor(parser, parser->m_bufferPtr, parser->m_parseEndPtr,
+- &parser->m_bufferPtr);
+-
+- if (parser->m_errorCode == XML_ERROR_NONE) {
+- switch (parser->m_parsingStatus.parsing) {
+- case XML_SUSPENDED:
+- /* While we added no new data, the finalBuffer flag may have caused
+- * us to parse previously-unparsed data in the internal buffer.
+- * If that triggered a callback to the application, it would have
+- * had an opportunity to suspend parsing. */
+- XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
+- parser->m_bufferPtr, &parser->m_position);
+- parser->m_positionPtr = parser->m_bufferPtr;
+- return XML_STATUS_SUSPENDED;
+- case XML_INITIALIZED:
+- case XML_PARSING:
+- parser->m_parsingStatus.parsing = XML_FINISHED;
+- /* fall through */
+- default:
+- return XML_STATUS_OK;
+- }
+- }
+- parser->m_eventEndPtr = parser->m_eventPtr;
+- parser->m_processor = errorProcessor;
+- return XML_STATUS_ERROR;
+- }
+ #ifndef XML_CONTEXT_BYTES
+- else if (parser->m_bufferPtr == parser->m_bufferEnd) {
++ if (parser->m_bufferPtr == parser->m_bufferEnd) {
+ const char *end;
+ int nLeftOver;
+ enum XML_Status result;
+@@ -2006,15 +1968,14 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
+ return result;
+ }
+ #endif /* not defined XML_CONTEXT_BYTES */
+- else {
+- void *buff = XML_GetBuffer(parser, len);
+- if (buff == NULL)
+- return XML_STATUS_ERROR;
+- else {
+- memcpy(buff, s, len);
+- return XML_ParseBuffer(parser, len, isFinal);
+- }
++ void *buff = XML_GetBuffer(parser, len);
++ if (buff == NULL)
++ return XML_STATUS_ERROR;
++ if (len > 0) {
++ assert(s != NULL); // make sure s==NULL && len!=0 was rejected above
++ memcpy(buff, s, len);
+ }
++ return XML_ParseBuffer(parser, len, isFinal);
+ }
+
+ enum XML_Status XMLCALL
+--
+2.40.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2023-52425-0009.patch b/meta/recipes-core/expat/expat/CVE-2023-52425-0009.patch
new file mode 100644
index 0000000000..9c1157faac
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2023-52425-0009.patch
@@ -0,0 +1,52 @@
+From ad9c01be8ee5d3d5cac2bfd3949ad764541d35e7 Mon Sep 17 00:00:00 2001
+From: Snild Dolkow
+Date: Thu, 26 Oct 2023 13:55:02 +0200
+Subject: [PATCH] Make external entity parser inherit partial token heuristic
+ setting
+
+The test is essentially a copy of the existing test for the setter,
+adapted to run on the external parser instead of the original one.
+
+Suggested-by: Sebastian Pipping
+CI-fighting-assistance-by: Sebastian Pipping
+
+CVE: CVE-2023-52425
+
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/ad9c01be8ee5d3d5cac2bfd3949ad764541d35e7]
+
+Signed-off-by: Meenali Gupta
+---
+ lib/xmlparse.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index f4ff66e..6746d70 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -1346,6 +1346,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+ to worry which hash secrets each table has.
+ */
+ unsigned long oldhash_secret_salt;
++ XML_Bool oldReparseDeferralEnabled;
+
+ /* Validate the oldParser parameter before we pull everything out of it */
+ if (oldParser == NULL)
+@@ -1390,6 +1391,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+ to worry which hash secrets each table has.
+ */
+ oldhash_secret_salt = parser->m_hash_secret_salt;
++ oldReparseDeferralEnabled = parser->m_reparseDeferralEnabled;
+
+ #ifdef XML_DTD
+ if (! context)
+@@ -1442,6 +1444,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+ parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+ parser->m_ns_triplets = oldns_triplets;
+ parser->m_hash_secret_salt = oldhash_secret_salt;
++ parser->m_reparseDeferralEnabled = oldReparseDeferralEnabled;
+ parser->m_parentParser = oldParser;
+ #ifdef XML_DTD
+ parser->m_paramEntityParsing = oldParamEntityParsing;
+--
+2.40.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2023-52425-0010.patch b/meta/recipes-core/expat/expat/CVE-2023-52425-0010.patch
new file mode 100644
index 0000000000..3fbf69de08
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2023-52425-0010.patch
@@ -0,0 +1,111 @@
+From 60b74209899a67d426d208662674b55a5eed918c Mon Sep 17 00:00:00 2001
+From: Snild Dolkow
+Date: Wed, 4 Oct 2023 16:00:14 +0200
+Subject: [PATCH] Bypass partial token heuristic when close to maximum buffer
+ size
+
+For huge tokens, we may end up in a situation where the partial token
+parse deferral heuristic demands more bytes than Expat's maximum buffer
+size (currently ~half of INT_MAX) could fit.
+
+INT_MAX/2 is 1024 MiB on most systems. Clearly, a token of 950 MiB could
+fit in that buffer, but the reparse threshold might be such that
+callProcessor() will defer it, allowing the app to keep filling the
+buffer until XML_GetBuffer() eventually returns a memory error.
+
+By bypassing the heuristic when we're getting close to the maximum
+buffer size, it will once again be possible to parse tokens in the size
+range INT_MAX/2/ratio < size < INT_MAX/2 reliably.
+
+We subtract the last buffer fill size as a way to detect that the next
+XML_GetBuffer() call has a risk of returning a memory error -- assuming
+that the application is likely to keep using the same (or smaller) fill.
+
+We subtract XML_CONTEXT_BYTES because that's the maximum amount of bytes
+that could remain at the start of the buffer, preceding the partial
+token. Technically, it could be fewer bytes, but XML_CONTEXT_BYTES is
+normally small relative to INT_MAX, and is much simpler to use.
+
+Co-authored-by: Sebastian Pipping
+
+CVE: CVE-2023-52425
+
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/60b74209899a67d426d208662674b55a5eed918c]
+
+Signed-off-by: Meenali Gupta
+---
+ lib/xmlparse.c | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 6746d70..32c57f6 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -205,6 +205,8 @@ typedef char ICHAR;
+ /* Do safe (NULL-aware) pointer arithmetic */
+ #define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
+
++#define EXPAT_MIN(a, b) (((a) < (b)) ? (a) : (b))
++
+ #include "internal.h"
+ #include "xmltok.h"
+ #include "xmlrole.h"
+@@ -634,6 +636,7 @@ struct XML_ParserStruct {
+ const char *m_parseEndPtr;
+ size_t m_partialTokenBytesBefore; /* used in heuristic to avoid O(n^2) */
+ XML_Bool m_reparseDeferralEnabled;
++ int m_lastBufferRequestSize;
+ XML_Char *m_dataBuf;
+ XML_Char *m_dataBufEnd;
+ XML_StartElementHandler m_startElementHandler;
+@@ -975,7 +978,18 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
+ // Heuristic: don't try to parse a partial token again until the amount of
+ // available data has increased significantly.
+ const size_t had_before = parser->m_partialTokenBytesBefore;
+- const bool enough = (have_now >= 2 * had_before);
++ // ...but *do* try anyway if we're close to reaching the max buffer size.
++ size_t close_to_maxbuf = INT_MAX / 2 + (INT_MAX & 1); // round up
++#if XML_CONTEXT_BYTES > 0
++ // subtract XML_CONTEXT_BYTES, but don't go below zero
++ close_to_maxbuf -= EXPAT_MIN(close_to_maxbuf, XML_CONTEXT_BYTES);
++#endif
++ // subtract the last buffer fill size, but don't go below zero
++ // m_lastBufferRequestSize is never assigned a value < 0, so the cast is ok
++ close_to_maxbuf
++ -= EXPAT_MIN(close_to_maxbuf, (size_t)parser->m_lastBufferRequestSize);
++ const bool enough
++ = (have_now >= 2 * had_before) || (have_now > close_to_maxbuf);
+
+ if (! enough) {
+ *endPtr = start; // callers may expect this to be set
+@@ -1177,6 +1191,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
+ parser->m_parseEndPtr = NULL;
+ parser->m_partialTokenBytesBefore = 0;
+ parser->m_reparseDeferralEnabled = g_reparseDeferralEnabledDefault;
++ parser->m_lastBufferRequestSize = 0;
+ parser->m_declElementType = NULL;
+ parser->m_declAttributeId = NULL;
+ parser->m_declEntity = NULL;
+@@ -1911,6 +1926,9 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
+ parser->m_processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
++ // though this isn't a buffer request, we assume that `len` is the app's
++ // preferred buffer fill size, and therefore save it here.
++ parser->m_lastBufferRequestSize = len;
+ parser->m_parseEndByteIndex += len;
+ parser->m_positionPtr = s;
+ parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
+@@ -2064,6 +2082,9 @@ XML_GetBuffer(XML_Parser parser, int len) {
+ default:;
+ }
+
++ // whether or not the request succeeds, `len` seems to be the app's preferred
++ // buffer fill size; remember it.
++ parser->m_lastBufferRequestSize = len;
+ if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)
+ || parser->m_buffer == NULL) {
+ #ifdef XML_CONTEXT_BYTES
+--
+2.40.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2023-52425-0011.patch b/meta/recipes-core/expat/expat/CVE-2023-52425-0011.patch
new file mode 100644
index 0000000000..800aaff544
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2023-52425-0011.patch
@@ -0,0 +1,89 @@
+From 3d8141d26a3b01ff948e00956cb0723a89dadf7f Mon Sep 17 00:00:00 2001
+From: Snild Dolkow
+Date: Mon, 20 Nov 2023 16:11:24 +0100
+Subject: [PATCH] Bypass partial token heuristic when nearing full buffer
+
+...instead of only when approaching the maximum buffer size INT/2+1.
+
+We'd like to give applications a chance to finish parsing a large token
+before buffer reallocation, in case the reallocation fails.
+
+By bypassing the reparse deferral heuristic when getting close to the
+filling the buffer, we give them this chance -- if the whole token is
+present in the buffer, it will be parsed at that time.
+
+This may come at the cost of some extra reparse attempts. For a token
+of n bytes, these extra parses cause us to scan over a maximum of
+2n bytes (... + n/8 + n/4 + n/2 + n). Therefore, parsing of big tokens
+remains O(n) in regard how many bytes we scan in attempts to parse. The
+cost in reality is lower than that, since the reparses that happen due
+to the bypass will affect m_partialTokenBytesBefore, delaying the next
+ratio-based reparse. Furthermore, only the first token that "breaks
+through" a buffer ceiling takes that extra reparse attempt; subsequent
+large tokens will only bypass the heuristic if they manage to hit the
+new buffer ceiling.
+
+Note that this cost analysis depends on the assumption that Expat grows
+its buffer by doubling it (or, more generally, grows it exponentially).
+If this changes, the cost of this bypass may increase. Hopefully, this
+would be caught by test_big_tokens_take_linear_time or the new test.
+
+The bypass logic assumes that the application uses a consistent fill.
+If the app increases its fill size, it may miss the bypass (and the
+normal heuristic will apply). If the app decreases its fill size, the
+bypass may be hit multiple times for the same buffer size. The very
+worst case would be to always fill half of the remaining buffer space,
+in which case parsing of a large n-byte token becomes O(n log n).
+
+As an added bonus, the new test case should be faster than the old one,
+since it doesn't have to go all the way to 1GiB to check the behavior.
+
+Finally, this change necessitated a small modification to two existing
+tests related to reparse deferral. These tests are testing the deferral
+enabled setting, and assume that reparsing will not happen for any other
+reason. By pre-growing the buffer, we make sure that this new deferral
+does not affect those test cases.
+
+CVE: CVE-2023-52425
+
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/3d8141d26a3b01ff948e00956cb0723a89dadf7f]
+
+Signed-off-by: Meenali Gupta
+---
+ lib/xmlparse.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 32c57f6..2830c1e 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -978,18 +978,18 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
+ // Heuristic: don't try to parse a partial token again until the amount of
+ // available data has increased significantly.
+ const size_t had_before = parser->m_partialTokenBytesBefore;
+- // ...but *do* try anyway if we're close to reaching the max buffer size.
+- size_t close_to_maxbuf = INT_MAX / 2 + (INT_MAX & 1); // round up
++ // ...but *do* try anyway if we're close to causing a reallocation.
++ size_t available_buffer
++ = EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
+ #if XML_CONTEXT_BYTES > 0
+- // subtract XML_CONTEXT_BYTES, but don't go below zero
+- close_to_maxbuf -= EXPAT_MIN(close_to_maxbuf, XML_CONTEXT_BYTES);
++ available_buffer -= EXPAT_MIN(available_buffer, XML_CONTEXT_BYTES);
+ #endif
+- // subtract the last buffer fill size, but don't go below zero
++ available_buffer
++ += EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd);
+ // m_lastBufferRequestSize is never assigned a value < 0, so the cast is ok
+- close_to_maxbuf
+- -= EXPAT_MIN(close_to_maxbuf, (size_t)parser->m_lastBufferRequestSize);
+ const bool enough
+- = (have_now >= 2 * had_before) || (have_now > close_to_maxbuf);
++ = (have_now >= 2 * had_before)
++ || ((size_t)parser->m_lastBufferRequestSize > available_buffer);
+
+ if (! enough) {
+ *endPtr = start; // callers may expect this to be set
+--
+2.40.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2023-52425-0012.patch b/meta/recipes-core/expat/expat/CVE-2023-52425-0012.patch
new file mode 100644
index 0000000000..8693e9449e
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2023-52425-0012.patch
@@ -0,0 +1,87 @@
+From 119ae277abaabd4d17b2e64300fec712ef403b28 Mon Sep 17 00:00:00 2001
+From: Snild Dolkow
+Date: Thu, 28 Sep 2023 18:26:19 +0200
+Subject: [PATCH] Grow buffer based on current size Until now, the buffer size
+ to grow to has been calculated based on the distance from the current parse
+ position to the end of the buffer. This means that the size of any
+ already-parsed data was not considered, leading to inconsistent buffer
+ growth.
+
+There was also a special case in XML_Parse() when XML_CONTEXT_BYTES was
+zero, where the buffer size would be set to twice the incoming string
+length. This patch replaces this with an XML_GetBuffer() call.
+
+Growing the buffer based on its total size makes its growth consistent.
+
+The commit includes a test that checks that we can reach the max buffer
+size (usually INT_MAX/2 + 1) regardless of previously parsed content.
+
+GitHub CI couldn't allocate the full 1GiB with MinGW/wine32, though it
+works locally with the same compiler and wine version. As a workaround,
+the test tries to malloc 1GiB, and reduces `maxbuf` to 512MiB in case
+of failure.
+
+CVE: CVE-2023-52425
+
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/119ae277abaabd4d17b2e64300fec712ef403b28]
+
+Signed-off-by: Meenali Gupta
+---
+ lib/xmlparse.c | 33 ++++++++++++++++-----------------
+ 1 file changed, 16 insertions(+), 17 deletions(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 2830c1e..81f9bb3 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -1961,23 +1961,22 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
+ &parser->m_position);
+ nLeftOver = s + len - end;
+ if (nLeftOver) {
+- if (parser->m_buffer == NULL
+- || nLeftOver > parser->m_bufferLim - parser->m_buffer) {
+- /* avoid _signed_ integer overflow */
+- char *temp = NULL;
+- const int bytesToAllocate = (int)((unsigned)len * 2U);
+- if (bytesToAllocate > 0) {
+- temp = (char *)REALLOC(parser, parser->m_buffer, bytesToAllocate);
+- }
+- if (temp == NULL) {
+- parser->m_errorCode = XML_ERROR_NO_MEMORY;
+- parser->m_eventPtr = parser->m_eventEndPtr = NULL;
+- parser->m_processor = errorProcessor;
+- return XML_STATUS_ERROR;
+- }
+- parser->m_buffer = temp;
+- parser->m_bufferLim = parser->m_buffer + bytesToAllocate;
++ // Back up and restore the parsing status to avoid XML_ERROR_SUSPENDED
++ // (and XML_ERROR_FINISHED) from XML_GetBuffer.
++ const enum XML_Parsing originalStatus = parser->m_parsingStatus.parsing;
++ parser->m_parsingStatus.parsing = XML_PARSING;
++ void *const temp = XML_GetBuffer(parser, nLeftOver);
++ parser->m_parsingStatus.parsing = originalStatus;
++ if (temp == NULL) {
++ // NOTE: parser->m_errorCode has already been set by XML_GetBuffer().
++ parser->m_eventPtr = parser->m_eventEndPtr = NULL;
++ parser->m_processor = errorProcessor;
++ return XML_STATUS_ERROR;
+ }
++ // Since we know that the buffer was empty and XML_CONTEXT_BYTES is 0, we
++ // don't have any data to preserve, and can copy straight into the start
++ // of the buffer rather than the GetBuffer return pointer (which may be
++ // pointing further into the allocated buffer).
+ memcpy(parser->m_buffer, end, nLeftOver);
+ }
+ parser->m_bufferPtr = parser->m_buffer;
+@@ -2135,7 +2134,7 @@ XML_GetBuffer(XML_Parser parser, int len) {
+ } else {
+ char *newBuf;
+ int bufferSize
+- = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferPtr);
++ = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer);
+ if (bufferSize == 0)
+ bufferSize = INIT_BUFFER_SIZE;
+ do {
+--
+2.40.0
+
diff --git a/meta/recipes-core/expat/expat_2.5.0.bb b/meta/recipes-core/expat/expat_2.5.0.bb
index 31e989cfe2..b7b5cce925 100644
--- a/meta/recipes-core/expat/expat_2.5.0.bb
+++ b/meta/recipes-core/expat/expat_2.5.0.bb
@@ -22,6 +22,18 @@ SRC_URI = "https://github.com/libexpat/libexpat/releases/download/R_${VERSION_TA
file://CVE-2023-52426-009.patch \
file://CVE-2023-52426-010.patch \
file://CVE-2023-52426-011.patch \
+ file://CVE-2023-52425-0001.patch \
+ file://CVE-2023-52425-0002.patch \
+ file://CVE-2023-52425-0003.patch \
+ file://CVE-2023-52425-0004.patch \
+ file://CVE-2023-52425-0005.patch \
+ file://CVE-2023-52425-0006.patch \
+ file://CVE-2023-52425-0007.patch \
+ file://CVE-2023-52425-0008.patch \
+ file://CVE-2023-52425-0009.patch \
+ file://CVE-2023-52425-0010.patch \
+ file://CVE-2023-52425-0011.patch \
+ file://CVE-2023-52425-0012.patch \
"
UPSTREAM_CHECK_URI = "https://github.com/libexpat/libexpat/releases/"