summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/expat/expat/CVE-2023-52425-0010.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/expat/expat/CVE-2023-52425-0010.patch')
-rw-r--r--meta/recipes-core/expat/expat/CVE-2023-52425-0010.patch111
1 files changed, 111 insertions, 0 deletions
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 @@
1From 60b74209899a67d426d208662674b55a5eed918c Mon Sep 17 00:00:00 2001
2From: Snild Dolkow <snild@sony.com>
3Date: Wed, 4 Oct 2023 16:00:14 +0200
4Subject: [PATCH] Bypass partial token heuristic when close to maximum buffer
5 size
6
7For huge tokens, we may end up in a situation where the partial token
8parse deferral heuristic demands more bytes than Expat's maximum buffer
9size (currently ~half of INT_MAX) could fit.
10
11INT_MAX/2 is 1024 MiB on most systems. Clearly, a token of 950 MiB could
12fit in that buffer, but the reparse threshold might be such that
13callProcessor() will defer it, allowing the app to keep filling the
14buffer until XML_GetBuffer() eventually returns a memory error.
15
16By bypassing the heuristic when we're getting close to the maximum
17buffer size, it will once again be possible to parse tokens in the size
18range INT_MAX/2/ratio < size < INT_MAX/2 reliably.
19
20We subtract the last buffer fill size as a way to detect that the next
21XML_GetBuffer() call has a risk of returning a memory error -- assuming
22that the application is likely to keep using the same (or smaller) fill.
23
24We subtract XML_CONTEXT_BYTES because that's the maximum amount of bytes
25that could remain at the start of the buffer, preceding the partial
26token. Technically, it could be fewer bytes, but XML_CONTEXT_BYTES is
27normally small relative to INT_MAX, and is much simpler to use.
28
29Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
30
31CVE: CVE-2023-52425
32
33Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/60b74209899a67d426d208662674b55a5eed918c]
34
35Signed-off-by: Meenali Gupta <meenali.gupta@windriver.com>
36---
37 lib/xmlparse.c | 23 ++++++++++++++++++++++-
38 1 file changed, 22 insertions(+), 1 deletion(-)
39
40diff --git a/lib/xmlparse.c b/lib/xmlparse.c
41index 6746d70..32c57f6 100644
42--- a/lib/xmlparse.c
43+++ b/lib/xmlparse.c
44@@ -205,6 +205,8 @@ typedef char ICHAR;
45 /* Do safe (NULL-aware) pointer arithmetic */
46 #define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
47
48+#define EXPAT_MIN(a, b) (((a) < (b)) ? (a) : (b))
49+
50 #include "internal.h"
51 #include "xmltok.h"
52 #include "xmlrole.h"
53@@ -634,6 +636,7 @@ struct XML_ParserStruct {
54 const char *m_parseEndPtr;
55 size_t m_partialTokenBytesBefore; /* used in heuristic to avoid O(n^2) */
56 XML_Bool m_reparseDeferralEnabled;
57+ int m_lastBufferRequestSize;
58 XML_Char *m_dataBuf;
59 XML_Char *m_dataBufEnd;
60 XML_StartElementHandler m_startElementHandler;
61@@ -975,7 +978,18 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
62 // Heuristic: don't try to parse a partial token again until the amount of
63 // available data has increased significantly.
64 const size_t had_before = parser->m_partialTokenBytesBefore;
65- const bool enough = (have_now >= 2 * had_before);
66+ // ...but *do* try anyway if we're close to reaching the max buffer size.
67+ size_t close_to_maxbuf = INT_MAX / 2 + (INT_MAX & 1); // round up
68+#if XML_CONTEXT_BYTES > 0
69+ // subtract XML_CONTEXT_BYTES, but don't go below zero
70+ close_to_maxbuf -= EXPAT_MIN(close_to_maxbuf, XML_CONTEXT_BYTES);
71+#endif
72+ // subtract the last buffer fill size, but don't go below zero
73+ // m_lastBufferRequestSize is never assigned a value < 0, so the cast is ok
74+ close_to_maxbuf
75+ -= EXPAT_MIN(close_to_maxbuf, (size_t)parser->m_lastBufferRequestSize);
76+ const bool enough
77+ = (have_now >= 2 * had_before) || (have_now > close_to_maxbuf);
78
79 if (! enough) {
80 *endPtr = start; // callers may expect this to be set
81@@ -1177,6 +1191,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
82 parser->m_parseEndPtr = NULL;
83 parser->m_partialTokenBytesBefore = 0;
84 parser->m_reparseDeferralEnabled = g_reparseDeferralEnabledDefault;
85+ parser->m_lastBufferRequestSize = 0;
86 parser->m_declElementType = NULL;
87 parser->m_declAttributeId = NULL;
88 parser->m_declEntity = NULL;
89@@ -1911,6 +1926,9 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
90 parser->m_processor = errorProcessor;
91 return XML_STATUS_ERROR;
92 }
93+ // though this isn't a buffer request, we assume that `len` is the app's
94+ // preferred buffer fill size, and therefore save it here.
95+ parser->m_lastBufferRequestSize = len;
96 parser->m_parseEndByteIndex += len;
97 parser->m_positionPtr = s;
98 parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
99@@ -2064,6 +2082,9 @@ XML_GetBuffer(XML_Parser parser, int len) {
100 default:;
101 }
102
103+ // whether or not the request succeeds, `len` seems to be the app's preferred
104+ // buffer fill size; remember it.
105+ parser->m_lastBufferRequestSize = len;
106 if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)
107 || parser->m_buffer == NULL) {
108 #ifdef XML_CONTEXT_BYTES
109--
1102.40.0
111