diff options
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.patch | 111 |
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 @@ | |||
1 | From 60b74209899a67d426d208662674b55a5eed918c Mon Sep 17 00:00:00 2001 | ||
2 | From: Snild Dolkow <snild@sony.com> | ||
3 | Date: Wed, 4 Oct 2023 16:00:14 +0200 | ||
4 | Subject: [PATCH] Bypass partial token heuristic when close to maximum buffer | ||
5 | size | ||
6 | |||
7 | For huge tokens, we may end up in a situation where the partial token | ||
8 | parse deferral heuristic demands more bytes than Expat's maximum buffer | ||
9 | size (currently ~half of INT_MAX) could fit. | ||
10 | |||
11 | INT_MAX/2 is 1024 MiB on most systems. Clearly, a token of 950 MiB could | ||
12 | fit in that buffer, but the reparse threshold might be such that | ||
13 | callProcessor() will defer it, allowing the app to keep filling the | ||
14 | buffer until XML_GetBuffer() eventually returns a memory error. | ||
15 | |||
16 | By bypassing the heuristic when we're getting close to the maximum | ||
17 | buffer size, it will once again be possible to parse tokens in the size | ||
18 | range INT_MAX/2/ratio < size < INT_MAX/2 reliably. | ||
19 | |||
20 | We subtract the last buffer fill size as a way to detect that the next | ||
21 | XML_GetBuffer() call has a risk of returning a memory error -- assuming | ||
22 | that the application is likely to keep using the same (or smaller) fill. | ||
23 | |||
24 | We subtract XML_CONTEXT_BYTES because that's the maximum amount of bytes | ||
25 | that could remain at the start of the buffer, preceding the partial | ||
26 | token. Technically, it could be fewer bytes, but XML_CONTEXT_BYTES is | ||
27 | normally small relative to INT_MAX, and is much simpler to use. | ||
28 | |||
29 | Co-authored-by: Sebastian Pipping <sebastian@pipping.org> | ||
30 | |||
31 | CVE: CVE-2023-52425 | ||
32 | |||
33 | Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/60b74209899a67d426d208662674b55a5eed918c] | ||
34 | |||
35 | Signed-off-by: Meenali Gupta <meenali.gupta@windriver.com> | ||
36 | --- | ||
37 | lib/xmlparse.c | 23 ++++++++++++++++++++++- | ||
38 | 1 file changed, 22 insertions(+), 1 deletion(-) | ||
39 | |||
40 | diff --git a/lib/xmlparse.c b/lib/xmlparse.c | ||
41 | index 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 | -- | ||
110 | 2.40.0 | ||
111 | |||