diff options
Diffstat (limited to 'meta/recipes-core/expat')
-rw-r--r-- | meta/recipes-core/expat/expat/CVE-2021-45960.patch | 65 | ||||
-rw-r--r-- | meta/recipes-core/expat/expat/CVE-2021-46143.patch | 49 | ||||
-rw-r--r-- | meta/recipes-core/expat/expat/CVE-2022-22822-27.patch | 257 | ||||
-rw-r--r-- | meta/recipes-core/expat/expat/CVE-2022-23852.patch | 33 | ||||
-rw-r--r-- | meta/recipes-core/expat/expat/CVE-2022-23990.patch | 49 | ||||
-rw-r--r-- | meta/recipes-core/expat/expat/CVE-2022-25235.patch | 261 | ||||
-rw-r--r-- | meta/recipes-core/expat/expat/CVE-2022-25236-1.patch | 116 | ||||
-rw-r--r-- | meta/recipes-core/expat/expat/CVE-2022-25236-2.patch | 232 | ||||
-rw-r--r-- | meta/recipes-core/expat/expat_2.2.10.bb | 14 |
9 files changed, 1073 insertions, 3 deletions
diff --git a/meta/recipes-core/expat/expat/CVE-2021-45960.patch b/meta/recipes-core/expat/expat/CVE-2021-45960.patch new file mode 100644 index 0000000000..523449e22c --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2021-45960.patch | |||
@@ -0,0 +1,65 @@ | |||
1 | From 0adcb34c49bee5b19bd29b16a578c510c23597ea Mon Sep 17 00:00:00 2001 | ||
2 | From: Sebastian Pipping <sebastian@pipping.org> | ||
3 | Date: Mon, 27 Dec 2021 20:15:02 +0100 | ||
4 | Subject: [PATCH] lib: Detect and prevent troublesome left shifts in function | ||
5 | storeAtts (CVE-2021-45960) | ||
6 | |||
7 | Upstream-Status: Backport: | ||
8 | https://github.com/libexpat/libexpat/pull/534/commits/0adcb34c49bee5b19bd29b16a578c510c23597ea | ||
9 | |||
10 | CVE: CVE-2021-45960 | ||
11 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
12 | |||
13 | --- | ||
14 | expat/lib/xmlparse.c | 31 +++++++++++++++++++++++++++++-- | ||
15 | 1 file changed, 29 insertions(+), 2 deletions(-) | ||
16 | |||
17 | diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c | ||
18 | index d730f41c3..b47c31b05 100644 | ||
19 | --- a/lib/xmlparse.c | ||
20 | +++ b/lib/xmlparse.c | ||
21 | @@ -3414,7 +3414,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, | ||
22 | if (nPrefixes) { | ||
23 | int j; /* hash table index */ | ||
24 | unsigned long version = parser->m_nsAttsVersion; | ||
25 | - int nsAttsSize = (int)1 << parser->m_nsAttsPower; | ||
26 | + | ||
27 | + /* Detect and prevent invalid shift */ | ||
28 | + if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) { | ||
29 | + return XML_ERROR_NO_MEMORY; | ||
30 | + } | ||
31 | + | ||
32 | + unsigned int nsAttsSize = 1u << parser->m_nsAttsPower; | ||
33 | unsigned char oldNsAttsPower = parser->m_nsAttsPower; | ||
34 | /* size of hash table must be at least 2 * (# of prefixed attributes) */ | ||
35 | if ((nPrefixes << 1) | ||
36 | @@ -3425,7 +3431,28 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, | ||
37 | ; | ||
38 | if (parser->m_nsAttsPower < 3) | ||
39 | parser->m_nsAttsPower = 3; | ||
40 | - nsAttsSize = (int)1 << parser->m_nsAttsPower; | ||
41 | + | ||
42 | + /* Detect and prevent invalid shift */ | ||
43 | + if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) { | ||
44 | + /* Restore actual size of memory in m_nsAtts */ | ||
45 | + parser->m_nsAttsPower = oldNsAttsPower; | ||
46 | + return XML_ERROR_NO_MEMORY; | ||
47 | + } | ||
48 | + | ||
49 | + nsAttsSize = 1u << parser->m_nsAttsPower; | ||
50 | + | ||
51 | + /* Detect and prevent integer overflow. | ||
52 | + * The preprocessor guard addresses the "always false" warning | ||
53 | + * from -Wtype-limits on platforms where | ||
54 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
55 | +#if UINT_MAX >= SIZE_MAX | ||
56 | + if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) { | ||
57 | + /* Restore actual size of memory in m_nsAtts */ | ||
58 | + parser->m_nsAttsPower = oldNsAttsPower; | ||
59 | + return XML_ERROR_NO_MEMORY; | ||
60 | + } | ||
61 | +#endif | ||
62 | + | ||
63 | temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, | ||
64 | nsAttsSize * sizeof(NS_ATT)); | ||
65 | if (! temp) { | ||
diff --git a/meta/recipes-core/expat/expat/CVE-2021-46143.patch b/meta/recipes-core/expat/expat/CVE-2021-46143.patch new file mode 100644 index 0000000000..b1a726d9a8 --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2021-46143.patch | |||
@@ -0,0 +1,49 @@ | |||
1 | From 85ae9a2d7d0e9358f356b33977b842df8ebaec2b Mon Sep 17 00:00:00 2001 | ||
2 | From: Sebastian Pipping <sebastian@pipping.org> | ||
3 | Date: Sat, 25 Dec 2021 20:52:08 +0100 | ||
4 | Subject: [PATCH] lib: Prevent integer overflow on m_groupSize in function | ||
5 | doProlog (CVE-2021-46143) | ||
6 | |||
7 | Upstream-Status: Backport: | ||
8 | https://github.com/libexpat/libexpat/pull/538/commits/85ae9a2d7d0e9358f356b33977b842df8ebaec2b | ||
9 | |||
10 | CVE: CVE-2021-46143 | ||
11 | |||
12 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
13 | --- | ||
14 | expat/lib/xmlparse.c | 15 +++++++++++++++ | ||
15 | 1 file changed, 15 insertions(+) | ||
16 | |||
17 | diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c | ||
18 | index b47c31b0..8f243126 100644 | ||
19 | --- a/lib/xmlparse.c | ||
20 | +++ b/lib/xmlparse.c | ||
21 | @@ -5046,6 +5046,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, | ||
22 | if (parser->m_prologState.level >= parser->m_groupSize) { | ||
23 | if (parser->m_groupSize) { | ||
24 | { | ||
25 | + /* Detect and prevent integer overflow */ | ||
26 | + if (parser->m_groupSize > (unsigned int)(-1) / 2u) { | ||
27 | + return XML_ERROR_NO_MEMORY; | ||
28 | + } | ||
29 | + | ||
30 | char *const new_connector = (char *)REALLOC( | ||
31 | parser, parser->m_groupConnector, parser->m_groupSize *= 2); | ||
32 | if (new_connector == NULL) { | ||
33 | @@ -5056,6 +5061,16 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, | ||
34 | } | ||
35 | |||
36 | if (dtd->scaffIndex) { | ||
37 | + /* Detect and prevent integer overflow. | ||
38 | + * The preprocessor guard addresses the "always false" warning | ||
39 | + * from -Wtype-limits on platforms where | ||
40 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
41 | +#if UINT_MAX >= SIZE_MAX | ||
42 | + if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) { | ||
43 | + return XML_ERROR_NO_MEMORY; | ||
44 | + } | ||
45 | +#endif | ||
46 | + | ||
47 | int *const new_scaff_index = (int *)REALLOC( | ||
48 | parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int)); | ||
49 | if (new_scaff_index == NULL) | ||
diff --git a/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch b/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch new file mode 100644 index 0000000000..e569fbc7ab --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch | |||
@@ -0,0 +1,257 @@ | |||
1 | From 9f93e8036e842329863bf20395b8fb8f73834d9e Mon Sep 17 00:00:00 2001 | ||
2 | From: Sebastian Pipping <sebastian@pipping.org> | ||
3 | Date: Thu, 30 Dec 2021 22:46:03 +0100 | ||
4 | Subject: [PATCH] lib: Prevent integer overflow at multiple places | ||
5 | (CVE-2022-22822 to CVE-2022-22827) | ||
6 | |||
7 | The involved functions are: | ||
8 | - addBinding (CVE-2022-22822) | ||
9 | - build_model (CVE-2022-22823) | ||
10 | - defineAttribute (CVE-2022-22824) | ||
11 | - lookup (CVE-2022-22825) | ||
12 | - nextScaffoldPart (CVE-2022-22826) | ||
13 | - storeAtts (CVE-2022-22827) | ||
14 | |||
15 | Upstream-Status: Backport: | ||
16 | https://github.com/libexpat/libexpat/pull/539/commits/9f93e8036e842329863bf20395b8fb8f73834d9e | ||
17 | |||
18 | CVE: CVE-2022-22822 CVE-2022-22823 CVE-2022-22824 CVE-2022-22825 CVE-2022-22826 CVE-2022-22827 | ||
19 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
20 | |||
21 | --- | ||
22 | expat/lib/xmlparse.c | 153 ++++++++++++++++++++++++++++++++++++++++++- | ||
23 | 1 file changed, 151 insertions(+), 2 deletions(-) | ||
24 | |||
25 | diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c | ||
26 | index 8f243126..575e73ee 100644 | ||
27 | --- a/lib/xmlparse.c | ||
28 | +++ b/lib/xmlparse.c | ||
29 | @@ -3261,13 +3261,38 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, | ||
30 | |||
31 | /* get the attributes from the tokenizer */ | ||
32 | n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts); | ||
33 | + | ||
34 | + /* Detect and prevent integer overflow */ | ||
35 | + if (n > INT_MAX - nDefaultAtts) { | ||
36 | + return XML_ERROR_NO_MEMORY; | ||
37 | + } | ||
38 | + | ||
39 | if (n + nDefaultAtts > parser->m_attsSize) { | ||
40 | int oldAttsSize = parser->m_attsSize; | ||
41 | ATTRIBUTE *temp; | ||
42 | #ifdef XML_ATTR_INFO | ||
43 | XML_AttrInfo *temp2; | ||
44 | #endif | ||
45 | + | ||
46 | + /* Detect and prevent integer overflow */ | ||
47 | + if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE) | ||
48 | + || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) { | ||
49 | + return XML_ERROR_NO_MEMORY; | ||
50 | + } | ||
51 | + | ||
52 | parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; | ||
53 | + | ||
54 | + /* Detect and prevent integer overflow. | ||
55 | + * The preprocessor guard addresses the "always false" warning | ||
56 | + * from -Wtype-limits on platforms where | ||
57 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
58 | +#if UINT_MAX >= SIZE_MAX | ||
59 | + if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) { | ||
60 | + parser->m_attsSize = oldAttsSize; | ||
61 | + return XML_ERROR_NO_MEMORY; | ||
62 | + } | ||
63 | +#endif | ||
64 | + | ||
65 | temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, | ||
66 | parser->m_attsSize * sizeof(ATTRIBUTE)); | ||
67 | if (temp == NULL) { | ||
68 | @@ -3276,6 +3301,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, | ||
69 | } | ||
70 | parser->m_atts = temp; | ||
71 | #ifdef XML_ATTR_INFO | ||
72 | + /* Detect and prevent integer overflow. | ||
73 | + * The preprocessor guard addresses the "always false" warning | ||
74 | + * from -Wtype-limits on platforms where | ||
75 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
76 | +# if UINT_MAX >= SIZE_MAX | ||
77 | + if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) { | ||
78 | + parser->m_attsSize = oldAttsSize; | ||
79 | + return XML_ERROR_NO_MEMORY; | ||
80 | + } | ||
81 | +# endif | ||
82 | + | ||
83 | temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, | ||
84 | parser->m_attsSize * sizeof(XML_AttrInfo)); | ||
85 | if (temp2 == NULL) { | ||
86 | @@ -3610,9 +3646,31 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, | ||
87 | tagNamePtr->prefixLen = prefixLen; | ||
88 | for (i = 0; localPart[i++];) | ||
89 | ; /* i includes null terminator */ | ||
90 | + | ||
91 | + /* Detect and prevent integer overflow */ | ||
92 | + if (binding->uriLen > INT_MAX - prefixLen | ||
93 | + || i > INT_MAX - (binding->uriLen + prefixLen)) { | ||
94 | + return XML_ERROR_NO_MEMORY; | ||
95 | + } | ||
96 | + | ||
97 | n = i + binding->uriLen + prefixLen; | ||
98 | if (n > binding->uriAlloc) { | ||
99 | TAG *p; | ||
100 | + | ||
101 | + /* Detect and prevent integer overflow */ | ||
102 | + if (n > INT_MAX - EXPAND_SPARE) { | ||
103 | + return XML_ERROR_NO_MEMORY; | ||
104 | + } | ||
105 | + /* Detect and prevent integer overflow. | ||
106 | + * The preprocessor guard addresses the "always false" warning | ||
107 | + * from -Wtype-limits on platforms where | ||
108 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
109 | +#if UINT_MAX >= SIZE_MAX | ||
110 | + if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { | ||
111 | + return XML_ERROR_NO_MEMORY; | ||
112 | + } | ||
113 | +#endif | ||
114 | + | ||
115 | uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char)); | ||
116 | if (! uri) | ||
117 | return XML_ERROR_NO_MEMORY; | ||
118 | @@ -3708,6 +3766,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, | ||
119 | if (parser->m_freeBindingList) { | ||
120 | b = parser->m_freeBindingList; | ||
121 | if (len > b->uriAlloc) { | ||
122 | + /* Detect and prevent integer overflow */ | ||
123 | + if (len > INT_MAX - EXPAND_SPARE) { | ||
124 | + return XML_ERROR_NO_MEMORY; | ||
125 | + } | ||
126 | + | ||
127 | + /* Detect and prevent integer overflow. | ||
128 | + * The preprocessor guard addresses the "always false" warning | ||
129 | + * from -Wtype-limits on platforms where | ||
130 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
131 | +#if UINT_MAX >= SIZE_MAX | ||
132 | + if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { | ||
133 | + return XML_ERROR_NO_MEMORY; | ||
134 | + } | ||
135 | +#endif | ||
136 | + | ||
137 | XML_Char *temp = (XML_Char *)REALLOC( | ||
138 | parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); | ||
139 | if (temp == NULL) | ||
140 | @@ -3720,6 +3793,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, | ||
141 | b = (BINDING *)MALLOC(parser, sizeof(BINDING)); | ||
142 | if (! b) | ||
143 | return XML_ERROR_NO_MEMORY; | ||
144 | + | ||
145 | + /* Detect and prevent integer overflow */ | ||
146 | + if (len > INT_MAX - EXPAND_SPARE) { | ||
147 | + return XML_ERROR_NO_MEMORY; | ||
148 | + } | ||
149 | + /* Detect and prevent integer overflow. | ||
150 | + * The preprocessor guard addresses the "always false" warning | ||
151 | + * from -Wtype-limits on platforms where | ||
152 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
153 | +#if UINT_MAX >= SIZE_MAX | ||
154 | + if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { | ||
155 | + return XML_ERROR_NO_MEMORY; | ||
156 | + } | ||
157 | +#endif | ||
158 | + | ||
159 | b->uri | ||
160 | = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); | ||
161 | if (! b->uri) { | ||
162 | @@ -6141,7 +6229,24 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, | ||
163 | } | ||
164 | } else { | ||
165 | DEFAULT_ATTRIBUTE *temp; | ||
166 | + | ||
167 | + /* Detect and prevent integer overflow */ | ||
168 | + if (type->allocDefaultAtts > INT_MAX / 2) { | ||
169 | + return 0; | ||
170 | + } | ||
171 | + | ||
172 | int count = type->allocDefaultAtts * 2; | ||
173 | + | ||
174 | + /* Detect and prevent integer overflow. | ||
175 | + * The preprocessor guard addresses the "always false" warning | ||
176 | + * from -Wtype-limits on platforms where | ||
177 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
178 | +#if UINT_MAX >= SIZE_MAX | ||
179 | + if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) { | ||
180 | + return 0; | ||
181 | + } | ||
182 | +#endif | ||
183 | + | ||
184 | temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts, | ||
185 | (count * sizeof(DEFAULT_ATTRIBUTE))); | ||
186 | if (temp == NULL) | ||
187 | @@ -6792,8 +6897,20 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { | ||
188 | /* check for overflow (table is half full) */ | ||
189 | if (table->used >> (table->power - 1)) { | ||
190 | unsigned char newPower = table->power + 1; | ||
191 | + | ||
192 | + /* Detect and prevent invalid shift */ | ||
193 | + if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) { | ||
194 | + return NULL; | ||
195 | + } | ||
196 | + | ||
197 | size_t newSize = (size_t)1 << newPower; | ||
198 | unsigned long newMask = (unsigned long)newSize - 1; | ||
199 | + | ||
200 | + /* Detect and prevent integer overflow */ | ||
201 | + if (newSize > (size_t)(-1) / sizeof(NAMED *)) { | ||
202 | + return NULL; | ||
203 | + } | ||
204 | + | ||
205 | size_t tsize = newSize * sizeof(NAMED *); | ||
206 | NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); | ||
207 | if (! newV) | ||
208 | @@ -7143,6 +7260,20 @@ nextScaffoldPart(XML_Parser parser) { | ||
209 | if (dtd->scaffCount >= dtd->scaffSize) { | ||
210 | CONTENT_SCAFFOLD *temp; | ||
211 | if (dtd->scaffold) { | ||
212 | + /* Detect and prevent integer overflow */ | ||
213 | + if (dtd->scaffSize > UINT_MAX / 2u) { | ||
214 | + return -1; | ||
215 | + } | ||
216 | + /* Detect and prevent integer overflow. | ||
217 | + * The preprocessor guard addresses the "always false" warning | ||
218 | + * from -Wtype-limits on platforms where | ||
219 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
220 | +#if UINT_MAX >= SIZE_MAX | ||
221 | + if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) { | ||
222 | + return -1; | ||
223 | + } | ||
224 | +#endif | ||
225 | + | ||
226 | temp = (CONTENT_SCAFFOLD *)REALLOC( | ||
227 | parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); | ||
228 | if (temp == NULL) | ||
229 | @@ -7212,8 +7343,26 @@ build_model(XML_Parser parser) { | ||
230 | XML_Content *ret; | ||
231 | XML_Content *cpos; | ||
232 | XML_Char *str; | ||
233 | - int allocsize = (dtd->scaffCount * sizeof(XML_Content) | ||
234 | - + (dtd->contentStringLen * sizeof(XML_Char))); | ||
235 | + | ||
236 | + /* Detect and prevent integer overflow. | ||
237 | + * The preprocessor guard addresses the "always false" warning | ||
238 | + * from -Wtype-limits on platforms where | ||
239 | + * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ | ||
240 | +#if UINT_MAX >= SIZE_MAX | ||
241 | + if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) { | ||
242 | + return NULL; | ||
243 | + } | ||
244 | + if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) { | ||
245 | + return NULL; | ||
246 | + } | ||
247 | +#endif | ||
248 | + if (dtd->scaffCount * sizeof(XML_Content) | ||
249 | + > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) { | ||
250 | + return NULL; | ||
251 | + } | ||
252 | + | ||
253 | + const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content) | ||
254 | + + (dtd->contentStringLen * sizeof(XML_Char))); | ||
255 | |||
256 | ret = (XML_Content *)MALLOC(parser, allocsize); | ||
257 | if (! ret) | ||
diff --git a/meta/recipes-core/expat/expat/CVE-2022-23852.patch b/meta/recipes-core/expat/expat/CVE-2022-23852.patch new file mode 100644 index 0000000000..41425c108b --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-23852.patch | |||
@@ -0,0 +1,33 @@ | |||
1 | From 847a645152f5ebc10ac63b74b604d0c1a79fae40 Mon Sep 17 00:00:00 2001 | ||
2 | From: Samanta Navarro <ferivoz@riseup.net> | ||
3 | Date: Sat, 22 Jan 2022 17:48:00 +0100 | ||
4 | Subject: [PATCH] lib: Detect and prevent integer overflow in XML_GetBuffer | ||
5 | (CVE-2022-23852) | ||
6 | |||
7 | Upstream-Status: Backport: | ||
8 | https://github.com/libexpat/libexpat/commit/847a645152f5ebc10ac63b74b604d0c1a79fae40 | ||
9 | |||
10 | CVE: CVE-2022-23852 | ||
11 | |||
12 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
13 | |||
14 | --- | ||
15 | expat/lib/xmlparse.c | 5 +++++ | ||
16 | 1 file changed, 5 insertions(+) | ||
17 | |||
18 | diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c | ||
19 | index d54af683..5ce31402 100644 | ||
20 | --- a/lib/xmlparse.c | ||
21 | +++ b/lib/xmlparse.c | ||
22 | @@ -2067,6 +2067,11 @@ XML_GetBuffer(XML_Parser parser, int len) { | ||
23 | keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer); | ||
24 | if (keep > XML_CONTEXT_BYTES) | ||
25 | keep = XML_CONTEXT_BYTES; | ||
26 | + /* Detect and prevent integer overflow */ | ||
27 | + if (keep > INT_MAX - neededSize) { | ||
28 | + parser->m_errorCode = XML_ERROR_NO_MEMORY; | ||
29 | + return NULL; | ||
30 | + } | ||
31 | neededSize += keep; | ||
32 | #endif /* defined XML_CONTEXT_BYTES */ | ||
33 | if (neededSize | ||
diff --git a/meta/recipes-core/expat/expat/CVE-2022-23990.patch b/meta/recipes-core/expat/expat/CVE-2022-23990.patch new file mode 100644 index 0000000000..c599517b3e --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-23990.patch | |||
@@ -0,0 +1,49 @@ | |||
1 | From ede41d1e186ed2aba88a06e84cac839b770af3a1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sebastian Pipping <sebastian@pipping.org> | ||
3 | Date: Wed, 26 Jan 2022 02:36:43 +0100 | ||
4 | Subject: [PATCH] lib: Prevent integer overflow in doProlog (CVE-2022-23990) | ||
5 | |||
6 | The change from "int nameLen" to "size_t nameLen" | ||
7 | addresses the overflow on "nameLen++" in code | ||
8 | "for (; name[nameLen++];)" right above the second | ||
9 | change in the patch. | ||
10 | |||
11 | Upstream-Status: Backport: | ||
12 | https://github.com/libexpat/libexpat/pull/551/commits/ede41d1e186ed2aba88a06e84cac839b770af3a1 | ||
13 | |||
14 | CVE: CVE-2022-23990 | ||
15 | |||
16 | Signed-off-by: Steve Sakoman <steve@sakoman.com> | ||
17 | |||
18 | --- | ||
19 | lib/xmlparse.c | 10 ++++++++-- | ||
20 | 1 file changed, 8 insertions(+), 2 deletions(-) | ||
21 | |||
22 | diff --git a/lib/xmlparse.c b/expat/lib/xmlparse.c | ||
23 | index 5ce31402..d1d17005 100644 | ||
24 | --- a/lib/xmlparse.c | ||
25 | +++ b/lib/xmlparse.c | ||
26 | @@ -5372,7 +5372,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, | ||
27 | if (dtd->in_eldecl) { | ||
28 | ELEMENT_TYPE *el; | ||
29 | const XML_Char *name; | ||
30 | - int nameLen; | ||
31 | + size_t nameLen; | ||
32 | const char *nxt | ||
33 | = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar); | ||
34 | int myindex = nextScaffoldPart(parser); | ||
35 | @@ -5388,7 +5388,13 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, | ||
36 | nameLen = 0; | ||
37 | for (; name[nameLen++];) | ||
38 | ; | ||
39 | - dtd->contentStringLen += nameLen; | ||
40 | + | ||
41 | + /* Detect and prevent integer overflow */ | ||
42 | + if (nameLen > UINT_MAX - dtd->contentStringLen) { | ||
43 | + return XML_ERROR_NO_MEMORY; | ||
44 | + } | ||
45 | + | ||
46 | + dtd->contentStringLen += (unsigned)nameLen; | ||
47 | if (parser->m_elementDeclHandler) | ||
48 | handleDefault = XML_FALSE; | ||
49 | } | ||
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25235.patch b/meta/recipes-core/expat/expat/CVE-2022-25235.patch new file mode 100644 index 0000000000..9febeae609 --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-25235.patch | |||
@@ -0,0 +1,261 @@ | |||
1 | Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/306b721] | ||
2 | CVE: CVE-2022-25235 | ||
3 | |||
4 | The commit is a merge commit, and this patch is created by: | ||
5 | |||
6 | $ git show -m -p --stat 306b72134f157bbfd1637b20a22cabf4acfa136a | ||
7 | |||
8 | Remove modification for expat/Changes which fails to be applied. | ||
9 | |||
10 | Signed-off-by: Kai Kang <kai.kang@windriver.com> | ||
11 | |||
12 | commit 306b72134f157bbfd1637b20a22cabf4acfa136a (from 2cc97e875ef84da4bcf55156c83599116f7523b4) | ||
13 | Merge: 2cc97e87 c16300f0 | ||
14 | Author: Sebastian Pipping <sebastian@pipping.org> | ||
15 | Date: Fri Feb 18 20:12:32 2022 +0100 | ||
16 | |||
17 | Merge pull request #562 from libexpat/utf8-security | ||
18 | |||
19 | [CVE-2022-25235] lib: Protect against malformed encoding (e.g. malformed UTF-8) | ||
20 | --- | ||
21 | expat/Changes | 7 ++++ | ||
22 | expat/lib/xmltok.c | 5 --- | ||
23 | expat/lib/xmltok_impl.c | 18 ++++---- | ||
24 | expat/tests/runtests.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ | ||
25 | 4 files changed, 127 insertions(+), 12 deletions(-) | ||
26 | |||
27 | diff --git a/lib/xmltok.c b/lib/xmltok.c | ||
28 | index a72200e8..3bddf125 100644 | ||
29 | --- a/lib/xmltok.c | ||
30 | +++ b/lib/xmltok.c | ||
31 | @@ -98,11 +98,6 @@ | ||
32 | + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \ | ||
33 | & (1u << (((byte)[2]) & 0x1F))) | ||
34 | |||
35 | -#define UTF8_GET_NAMING(pages, p, n) \ | ||
36 | - ((n) == 2 \ | ||
37 | - ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ | ||
38 | - : ((n) == 3 ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) : 0)) | ||
39 | - | ||
40 | /* Detection of invalid UTF-8 sequences is based on Table 3.1B | ||
41 | of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/ | ||
42 | with the additional restriction of not allowing the Unicode | ||
43 | diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c | ||
44 | index 0430591b..84ff35f9 100644 | ||
45 | --- a/lib/xmltok_impl.c | ||
46 | +++ b/lib/xmltok_impl.c | ||
47 | @@ -69,7 +69,7 @@ | ||
48 | case BT_LEAD##n: \ | ||
49 | if (end - ptr < n) \ | ||
50 | return XML_TOK_PARTIAL_CHAR; \ | ||
51 | - if (! IS_NAME_CHAR(enc, ptr, n)) { \ | ||
52 | + if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NAME_CHAR(enc, ptr, n)) { \ | ||
53 | *nextTokPtr = ptr; \ | ||
54 | return XML_TOK_INVALID; \ | ||
55 | } \ | ||
56 | @@ -98,7 +98,7 @@ | ||
57 | case BT_LEAD##n: \ | ||
58 | if (end - ptr < n) \ | ||
59 | return XML_TOK_PARTIAL_CHAR; \ | ||
60 | - if (! IS_NMSTRT_CHAR(enc, ptr, n)) { \ | ||
61 | + if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \ | ||
62 | *nextTokPtr = ptr; \ | ||
63 | return XML_TOK_INVALID; \ | ||
64 | } \ | ||
65 | @@ -1142,6 +1142,10 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, | ||
66 | case BT_LEAD##n: \ | ||
67 | if (end - ptr < n) \ | ||
68 | return XML_TOK_PARTIAL_CHAR; \ | ||
69 | + if (IS_INVALID_CHAR(enc, ptr, n)) { \ | ||
70 | + *nextTokPtr = ptr; \ | ||
71 | + return XML_TOK_INVALID; \ | ||
72 | + } \ | ||
73 | if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ | ||
74 | ptr += n; \ | ||
75 | tok = XML_TOK_NAME; \ | ||
76 | @@ -1270,7 +1274,7 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, | ||
77 | switch (BYTE_TYPE(enc, ptr)) { | ||
78 | # define LEAD_CASE(n) \ | ||
79 | case BT_LEAD##n: \ | ||
80 | - ptr += n; \ | ||
81 | + ptr += n; /* NOTE: The encoding has already been validated. */ \ | ||
82 | break; | ||
83 | LEAD_CASE(2) | ||
84 | LEAD_CASE(3) | ||
85 | @@ -1339,7 +1343,7 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, | ||
86 | switch (BYTE_TYPE(enc, ptr)) { | ||
87 | # define LEAD_CASE(n) \ | ||
88 | case BT_LEAD##n: \ | ||
89 | - ptr += n; \ | ||
90 | + ptr += n; /* NOTE: The encoding has already been validated. */ \ | ||
91 | break; | ||
92 | LEAD_CASE(2) | ||
93 | LEAD_CASE(3) | ||
94 | @@ -1518,7 +1522,7 @@ PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax, | ||
95 | state = inName; \ | ||
96 | } | ||
97 | # define LEAD_CASE(n) \ | ||
98 | - case BT_LEAD##n: \ | ||
99 | + case BT_LEAD##n: /* NOTE: The encoding has already been validated. */ \ | ||
100 | START_NAME ptr += (n - MINBPC(enc)); \ | ||
101 | break; | ||
102 | LEAD_CASE(2) | ||
103 | @@ -1730,7 +1734,7 @@ PREFIX(nameLength)(const ENCODING *enc, const char *ptr) { | ||
104 | switch (BYTE_TYPE(enc, ptr)) { | ||
105 | # define LEAD_CASE(n) \ | ||
106 | case BT_LEAD##n: \ | ||
107 | - ptr += n; \ | ||
108 | + ptr += n; /* NOTE: The encoding has already been validated. */ \ | ||
109 | break; | ||
110 | LEAD_CASE(2) | ||
111 | LEAD_CASE(3) | ||
112 | @@ -1775,7 +1779,7 @@ PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end, | ||
113 | switch (BYTE_TYPE(enc, ptr)) { | ||
114 | # define LEAD_CASE(n) \ | ||
115 | case BT_LEAD##n: \ | ||
116 | - ptr += n; \ | ||
117 | + ptr += n; /* NOTE: The encoding has already been validated. */ \ | ||
118 | pos->columnNumber++; \ | ||
119 | break; | ||
120 | LEAD_CASE(2) | ||
121 | diff --git a/tests/runtests.c b/tests/runtests.c | ||
122 | index bc5344b1..9b155b82 100644 | ||
123 | --- a/tests/runtests.c | ||
124 | +++ b/tests/runtests.c | ||
125 | @@ -5998,6 +5998,105 @@ START_TEST(test_utf8_in_cdata_section_2) { | ||
126 | } | ||
127 | END_TEST | ||
128 | |||
129 | +START_TEST(test_utf8_in_start_tags) { | ||
130 | + struct test_case { | ||
131 | + bool goodName; | ||
132 | + bool goodNameStart; | ||
133 | + const char *tagName; | ||
134 | + }; | ||
135 | + | ||
136 | + // The idea with the tests below is this: | ||
137 | + // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences | ||
138 | + // go to isNever and are hence not a concern. | ||
139 | + // | ||
140 | + // We start with a character that is a valid name character | ||
141 | + // (or even name-start character, see XML 1.0r4 spec) and then we flip | ||
142 | + // single bits at places where (1) the result leaves the UTF-8 encoding space | ||
143 | + // and (2) we stay in the same n-byte sequence family. | ||
144 | + // | ||
145 | + // The flipped bits are highlighted in angle brackets in comments, | ||
146 | + // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped | ||
147 | + // the most significant bit to 1 to leave UTF-8 encoding space. | ||
148 | + struct test_case cases[] = { | ||
149 | + // 1-byte UTF-8: [0xxx xxxx] | ||
150 | + {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':' | ||
151 | + {false, false, "\xBA"}, // [<1>011 1010] | ||
152 | + {true, false, "\x39"}, // [0011 1001] = ASCII nine '9' | ||
153 | + {false, false, "\xB9"}, // [<1>011 1001] | ||
154 | + | ||
155 | + // 2-byte UTF-8: [110x xxxx] [10xx xxxx] | ||
156 | + {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] = | ||
157 | + // Arabic small waw U+06E5 | ||
158 | + {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101] | ||
159 | + {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101] | ||
160 | + {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101] | ||
161 | + {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] = | ||
162 | + // combining char U+0301 | ||
163 | + {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001] | ||
164 | + {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001] | ||
165 | + {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001] | ||
166 | + | ||
167 | + // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx] | ||
168 | + {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] = | ||
169 | + // Devanagari Letter A U+0905 | ||
170 | + {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101] | ||
171 | + {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101] | ||
172 | + {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101] | ||
173 | + {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101] | ||
174 | + {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101] | ||
175 | + {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] = | ||
176 | + // combining char U+0901 | ||
177 | + {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001] | ||
178 | + {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001] | ||
179 | + {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001] | ||
180 | + {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001] | ||
181 | + {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001] | ||
182 | + }; | ||
183 | + const bool atNameStart[] = {true, false}; | ||
184 | + | ||
185 | + size_t i = 0; | ||
186 | + char doc[1024]; | ||
187 | + size_t failCount = 0; | ||
188 | + | ||
189 | + for (; i < sizeof(cases) / sizeof(cases[0]); i++) { | ||
190 | + size_t j = 0; | ||
191 | + for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) { | ||
192 | + const bool expectedSuccess | ||
193 | + = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName; | ||
194 | + sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName); | ||
195 | + XML_Parser parser = XML_ParserCreate(NULL); | ||
196 | + | ||
197 | + const enum XML_Status status | ||
198 | + = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE); | ||
199 | + | ||
200 | + bool success = true; | ||
201 | + if ((status == XML_STATUS_OK) != expectedSuccess) { | ||
202 | + success = false; | ||
203 | + } | ||
204 | + if ((status == XML_STATUS_ERROR) | ||
205 | + && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) { | ||
206 | + success = false; | ||
207 | + } | ||
208 | + | ||
209 | + if (! success) { | ||
210 | + fprintf( | ||
211 | + stderr, | ||
212 | + "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n", | ||
213 | + (unsigned)i + 1u, atNameStart[j] ? " " : "not ", | ||
214 | + (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser)); | ||
215 | + failCount++; | ||
216 | + } | ||
217 | + | ||
218 | + XML_ParserFree(parser); | ||
219 | + } | ||
220 | + } | ||
221 | + | ||
222 | + if (failCount > 0) { | ||
223 | + fail("UTF-8 regression detected"); | ||
224 | + } | ||
225 | +} | ||
226 | +END_TEST | ||
227 | + | ||
228 | /* Test trailing spaces in elements are accepted */ | ||
229 | static void XMLCALL | ||
230 | record_element_end_handler(void *userData, const XML_Char *name) { | ||
231 | @@ -6175,6 +6274,14 @@ START_TEST(test_bad_doctype) { | ||
232 | } | ||
233 | END_TEST | ||
234 | |||
235 | +START_TEST(test_bad_doctype_utf8) { | ||
236 | + const char *text = "<!DOCTYPE \xDB\x25" | ||
237 | + "doc><doc/>"; // [1101 1011] [<0>010 0101] | ||
238 | + expect_failure(text, XML_ERROR_INVALID_TOKEN, | ||
239 | + "Invalid UTF-8 in DOCTYPE not faulted"); | ||
240 | +} | ||
241 | +END_TEST | ||
242 | + | ||
243 | START_TEST(test_bad_doctype_utf16) { | ||
244 | const char text[] = | ||
245 | /* <!DOCTYPE doc [ \x06f2 ]><doc/> | ||
246 | @@ -11870,6 +11977,7 @@ make_suite(void) { | ||
247 | tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom); | ||
248 | tcase_add_test(tc_basic, test_utf8_in_cdata_section); | ||
249 | tcase_add_test(tc_basic, test_utf8_in_cdata_section_2); | ||
250 | + tcase_add_test(tc_basic, test_utf8_in_start_tags); | ||
251 | tcase_add_test(tc_basic, test_trailing_spaces_in_elements); | ||
252 | tcase_add_test(tc_basic, test_utf16_attribute); | ||
253 | tcase_add_test(tc_basic, test_utf16_second_attr); | ||
254 | @@ -11878,6 +11986,7 @@ make_suite(void) { | ||
255 | tcase_add_test(tc_basic, test_bad_attr_desc_keyword); | ||
256 | tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16); | ||
257 | tcase_add_test(tc_basic, test_bad_doctype); | ||
258 | + tcase_add_test(tc_basic, test_bad_doctype_utf8); | ||
259 | tcase_add_test(tc_basic, test_bad_doctype_utf16); | ||
260 | tcase_add_test(tc_basic, test_bad_doctype_plus); | ||
261 | tcase_add_test(tc_basic, test_bad_doctype_star); | ||
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch b/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch new file mode 100644 index 0000000000..ab53d99c8f --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch | |||
@@ -0,0 +1,116 @@ | |||
1 | Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/2cc97e87] | ||
2 | CVE: CVE-2022-25236 | ||
3 | |||
4 | The commit is a merge commit, and this patch is created by: | ||
5 | |||
6 | $ git diff -p --stat 2cc97e87~ 2cc97e87 | ||
7 | |||
8 | Remove modification for expat/Changes which fails to be applied. | ||
9 | |||
10 | Signed-off-by: Kai Kang <kai.kang@windriver.com> | ||
11 | |||
12 | commit 2cc97e875ef84da4bcf55156c83599116f7523b4 (from d477fdd284468f2ab822024e75702f2c1b254f42) | ||
13 | Merge: d477fdd2 e4d7e497 | ||
14 | Author: Sebastian Pipping <sebastian@pipping.org> | ||
15 | Date: Fri Feb 18 18:01:27 2022 +0100 | ||
16 | |||
17 | Merge pull request #561 from libexpat/namesep-security | ||
18 | |||
19 | [CVE-2022-25236] lib: Protect against insertion of namesep characters into namespace URIs | ||
20 | |||
21 | --- | ||
22 | expat/Changes | 16 ++++++++++++++++ | ||
23 | expat/lib/xmlparse.c | 17 +++++++++++++---- | ||
24 | expat/tests/runtests.c | 30 ++++++++++++++++++++++++++++++ | ||
25 | 3 files changed, 59 insertions(+), 4 deletions(-) | ||
26 | |||
27 | diff --git a/lib/xmlparse.c b/lib/xmlparse.c | ||
28 | index 7376aab1..c98e2e9f 100644 | ||
29 | --- a/lib/xmlparse.c | ||
30 | +++ b/lib/xmlparse.c | ||
31 | @@ -718,8 +718,7 @@ XML_ParserCreate(const XML_Char *encodingName) { | ||
32 | |||
33 | XML_Parser XMLCALL | ||
34 | XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) { | ||
35 | - XML_Char tmp[2]; | ||
36 | - *tmp = nsSep; | ||
37 | + XML_Char tmp[2] = {nsSep, 0}; | ||
38 | return XML_ParserCreate_MM(encodingName, NULL, tmp); | ||
39 | } | ||
40 | |||
41 | @@ -1344,8 +1343,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, | ||
42 | would be otherwise. | ||
43 | */ | ||
44 | if (parser->m_ns) { | ||
45 | - XML_Char tmp[2]; | ||
46 | - *tmp = parser->m_namespaceSeparator; | ||
47 | + XML_Char tmp[2] = {parser->m_namespaceSeparator, 0}; | ||
48 | parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); | ||
49 | } else { | ||
50 | parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); | ||
51 | @@ -3761,6 +3759,17 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, | ||
52 | if (! mustBeXML && isXMLNS | ||
53 | && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) | ||
54 | isXMLNS = XML_FALSE; | ||
55 | + | ||
56 | + // NOTE: While Expat does not validate namespace URIs against RFC 3986, | ||
57 | + // we have to at least make sure that the XML processor on top of | ||
58 | + // Expat (that is splitting tag names by namespace separator into | ||
59 | + // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused | ||
60 | + // by an attacker putting additional namespace separator characters | ||
61 | + // into namespace declarations. That would be ambiguous and not to | ||
62 | + // be expected. | ||
63 | + if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) { | ||
64 | + return XML_ERROR_SYNTAX; | ||
65 | + } | ||
66 | } | ||
67 | isXML = isXML && len == xmlLen; | ||
68 | isXMLNS = isXMLNS && len == xmlnsLen; | ||
69 | diff --git a/tests/runtests.c b/tests/runtests.c | ||
70 | index d07203f2..bc5344b1 100644 | ||
71 | --- a/tests/runtests.c | ||
72 | +++ b/tests/runtests.c | ||
73 | @@ -7220,6 +7220,35 @@ START_TEST(test_ns_double_colon_doctype) { | ||
74 | } | ||
75 | END_TEST | ||
76 | |||
77 | +START_TEST(test_ns_separator_in_uri) { | ||
78 | + struct test_case { | ||
79 | + enum XML_Status expectedStatus; | ||
80 | + const char *doc; | ||
81 | + }; | ||
82 | + struct test_case cases[] = { | ||
83 | + {XML_STATUS_OK, "<doc xmlns='one_two' />"}, | ||
84 | + {XML_STATUS_ERROR, "<doc xmlns='one
two' />"}, | ||
85 | + }; | ||
86 | + | ||
87 | + size_t i = 0; | ||
88 | + size_t failCount = 0; | ||
89 | + for (; i < sizeof(cases) / sizeof(cases[0]); i++) { | ||
90 | + XML_Parser parser = XML_ParserCreateNS(NULL, '\n'); | ||
91 | + XML_SetElementHandler(parser, dummy_start_element, dummy_end_element); | ||
92 | + if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc), | ||
93 | + /*isFinal*/ XML_TRUE) | ||
94 | + != cases[i].expectedStatus) { | ||
95 | + failCount++; | ||
96 | + } | ||
97 | + XML_ParserFree(parser); | ||
98 | + } | ||
99 | + | ||
100 | + if (failCount) { | ||
101 | + fail("Namespace separator handling is broken"); | ||
102 | + } | ||
103 | +} | ||
104 | +END_TEST | ||
105 | + | ||
106 | /* Control variable; the number of times duff_allocator() will successfully | ||
107 | * allocate */ | ||
108 | #define ALLOC_ALWAYS_SUCCEED (-1) | ||
109 | @@ -11905,6 +11934,7 @@ make_suite(void) { | ||
110 | tcase_add_test(tc_namespace, test_ns_utf16_doctype); | ||
111 | tcase_add_test(tc_namespace, test_ns_invalid_doctype); | ||
112 | tcase_add_test(tc_namespace, test_ns_double_colon_doctype); | ||
113 | + tcase_add_test(tc_namespace, test_ns_separator_in_uri); | ||
114 | |||
115 | suite_add_tcase(s, tc_misc); | ||
116 | tcase_add_checked_fixture(tc_misc, NULL, basic_teardown); | ||
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch b/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch new file mode 100644 index 0000000000..0f14c9631b --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch | |||
@@ -0,0 +1,232 @@ | |||
1 | Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/f178826b] | ||
2 | CVE: CVE-2022-25236 | ||
3 | |||
4 | The commit is a merge commit, and this patch is created by: | ||
5 | |||
6 | $ git show -m -p --stat f178826b | ||
7 | |||
8 | Remove changes for expat/Changes and reference.html which fail to be applied. | ||
9 | |||
10 | Signed-off-by: Kai Kang <kai.kang@windriver.com> | ||
11 | |||
12 | commit f178826bb1e9c8ee23202f1be55ad4ac7b649e84 (from c99e0e7f2b15b48848038992ecbb4480f957cfe9) | ||
13 | Merge: c99e0e7f 9579f7ea | ||
14 | Author: Sebastian Pipping <sebastian@pipping.org> | ||
15 | Date: Fri Mar 4 18:43:39 2022 +0100 | ||
16 | |||
17 | Merge pull request #577 from libexpat/namesep | ||
18 | |||
19 | lib: Relax fix to CVE-2022-25236 with regard to RFC 3986 URI characters (fixes #572) | ||
20 | --- | ||
21 | expat/Changes | 16 ++++++ | ||
22 | expat/doc/reference.html | 8 +++ | ||
23 | expat/lib/expat.h | 11 ++++ | ||
24 | expat/lib/xmlparse.c | 139 ++++++++++++++++++++++++++++++++++++++++++++--- | ||
25 | expat/tests/runtests.c | 8 ++- | ||
26 | 5 files changed, 171 insertions(+), 11 deletions(-) | ||
27 | |||
28 | diff --git a/lib/expat.h b/lib/expat.h | ||
29 | index 5ab493f7..181fc960 100644 | ||
30 | --- a/lib/expat.h | ||
31 | +++ b/lib/expat.h | ||
32 | @@ -239,6 +239,17 @@ XML_ParserCreate(const XML_Char *encoding); | ||
33 | and the local part will be concatenated without any separator. | ||
34 | It is a programming error to use the separator '\0' with namespace | ||
35 | triplets (see XML_SetReturnNSTriplet). | ||
36 | + If a namespace separator is chosen that can be part of a URI or | ||
37 | + part of an XML name, splitting an expanded name back into its | ||
38 | + 1, 2 or 3 original parts on application level in the element handler | ||
39 | + may end up vulnerable, so these are advised against; sane choices for | ||
40 | + a namespace separator are e.g. '\n' (line feed) and '|' (pipe). | ||
41 | + | ||
42 | + Note that Expat does not validate namespace URIs (beyond encoding) | ||
43 | + against RFC 3986 today (and is not required to do so with regard to | ||
44 | + the XML 1.0 namespaces specification) but it may start doing that | ||
45 | + in future releases. Before that, an application using Expat must | ||
46 | + be ready to receive namespace URIs containing non-URI characters. | ||
47 | */ | ||
48 | XMLPARSEAPI(XML_Parser) | ||
49 | XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); | ||
50 | diff --git a/lib/xmlparse.c b/lib/xmlparse.c | ||
51 | index 59da19c8..6fe2cf1e 100644 | ||
52 | --- a/lib/xmlparse.c | ||
53 | +++ b/lib/xmlparse.c | ||
54 | @@ -3705,6 +3705,117 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, | ||
55 | return XML_ERROR_NONE; | ||
56 | } | ||
57 | |||
58 | +static XML_Bool | ||
59 | +is_rfc3986_uri_char(XML_Char candidate) { | ||
60 | + // For the RFC 3986 ANBF grammar see | ||
61 | + // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A | ||
62 | + | ||
63 | + switch (candidate) { | ||
64 | + // From rule "ALPHA" (uppercase half) | ||
65 | + case 'A': | ||
66 | + case 'B': | ||
67 | + case 'C': | ||
68 | + case 'D': | ||
69 | + case 'E': | ||
70 | + case 'F': | ||
71 | + case 'G': | ||
72 | + case 'H': | ||
73 | + case 'I': | ||
74 | + case 'J': | ||
75 | + case 'K': | ||
76 | + case 'L': | ||
77 | + case 'M': | ||
78 | + case 'N': | ||
79 | + case 'O': | ||
80 | + case 'P': | ||
81 | + case 'Q': | ||
82 | + case 'R': | ||
83 | + case 'S': | ||
84 | + case 'T': | ||
85 | + case 'U': | ||
86 | + case 'V': | ||
87 | + case 'W': | ||
88 | + case 'X': | ||
89 | + case 'Y': | ||
90 | + case 'Z': | ||
91 | + | ||
92 | + // From rule "ALPHA" (lowercase half) | ||
93 | + case 'a': | ||
94 | + case 'b': | ||
95 | + case 'c': | ||
96 | + case 'd': | ||
97 | + case 'e': | ||
98 | + case 'f': | ||
99 | + case 'g': | ||
100 | + case 'h': | ||
101 | + case 'i': | ||
102 | + case 'j': | ||
103 | + case 'k': | ||
104 | + case 'l': | ||
105 | + case 'm': | ||
106 | + case 'n': | ||
107 | + case 'o': | ||
108 | + case 'p': | ||
109 | + case 'q': | ||
110 | + case 'r': | ||
111 | + case 's': | ||
112 | + case 't': | ||
113 | + case 'u': | ||
114 | + case 'v': | ||
115 | + case 'w': | ||
116 | + case 'x': | ||
117 | + case 'y': | ||
118 | + case 'z': | ||
119 | + | ||
120 | + // From rule "DIGIT" | ||
121 | + case '0': | ||
122 | + case '1': | ||
123 | + case '2': | ||
124 | + case '3': | ||
125 | + case '4': | ||
126 | + case '5': | ||
127 | + case '6': | ||
128 | + case '7': | ||
129 | + case '8': | ||
130 | + case '9': | ||
131 | + | ||
132 | + // From rule "pct-encoded" | ||
133 | + case '%': | ||
134 | + | ||
135 | + // From rule "unreserved" | ||
136 | + case '-': | ||
137 | + case '.': | ||
138 | + case '_': | ||
139 | + case '~': | ||
140 | + | ||
141 | + // From rule "gen-delims" | ||
142 | + case ':': | ||
143 | + case '/': | ||
144 | + case '?': | ||
145 | + case '#': | ||
146 | + case '[': | ||
147 | + case ']': | ||
148 | + case '@': | ||
149 | + | ||
150 | + // From rule "sub-delims" | ||
151 | + case '!': | ||
152 | + case '$': | ||
153 | + case '&': | ||
154 | + case '\'': | ||
155 | + case '(': | ||
156 | + case ')': | ||
157 | + case '*': | ||
158 | + case '+': | ||
159 | + case ',': | ||
160 | + case ';': | ||
161 | + case '=': | ||
162 | + return XML_TRUE; | ||
163 | + | ||
164 | + default: | ||
165 | + return XML_FALSE; | ||
166 | + } | ||
167 | +} | ||
168 | + | ||
169 | /* addBinding() overwrites the value of prefix->binding without checking. | ||
170 | Therefore one must keep track of the old value outside of addBinding(). | ||
171 | */ | ||
172 | @@ -3763,14 +3874,26 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, | ||
173 | && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) | ||
174 | isXMLNS = XML_FALSE; | ||
175 | |||
176 | - // NOTE: While Expat does not validate namespace URIs against RFC 3986, | ||
177 | - // we have to at least make sure that the XML processor on top of | ||
178 | - // Expat (that is splitting tag names by namespace separator into | ||
179 | - // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused | ||
180 | - // by an attacker putting additional namespace separator characters | ||
181 | - // into namespace declarations. That would be ambiguous and not to | ||
182 | - // be expected. | ||
183 | - if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) { | ||
184 | + // NOTE: While Expat does not validate namespace URIs against RFC 3986 | ||
185 | + // today (and is not REQUIRED to do so with regard to the XML 1.0 | ||
186 | + // namespaces specification) we have to at least make sure, that | ||
187 | + // the application on top of Expat (that is likely splitting expanded | ||
188 | + // element names ("qualified names") of form | ||
189 | + // "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces | ||
190 | + // in its element handler code) cannot be confused by an attacker | ||
191 | + // putting additional namespace separator characters into namespace | ||
192 | + // declarations. That would be ambiguous and not to be expected. | ||
193 | + // | ||
194 | + // While the HTML API docs of function XML_ParserCreateNS have been | ||
195 | + // advising against use of a namespace separator character that can | ||
196 | + // appear in a URI for >20 years now, some widespread applications | ||
197 | + // are using URI characters (':' (colon) in particular) for a | ||
198 | + // namespace separator, in practice. To keep these applications | ||
199 | + // functional, we only reject namespaces URIs containing the | ||
200 | + // application-chosen namespace separator if the chosen separator | ||
201 | + // is a non-URI character with regard to RFC 3986. | ||
202 | + if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator) | ||
203 | + && ! is_rfc3986_uri_char(uri[len])) { | ||
204 | return XML_ERROR_SYNTAX; | ||
205 | } | ||
206 | } | ||
207 | diff --git a/tests/runtests.c b/tests/runtests.c | ||
208 | index 60da868e..712706c4 100644 | ||
209 | --- a/tests/runtests.c | ||
210 | +++ b/tests/runtests.c | ||
211 | @@ -7406,16 +7406,18 @@ START_TEST(test_ns_separator_in_uri) { | ||
212 | struct test_case { | ||
213 | enum XML_Status expectedStatus; | ||
214 | const char *doc; | ||
215 | + XML_Char namesep; | ||
216 | }; | ||
217 | struct test_case cases[] = { | ||
218 | - {XML_STATUS_OK, "<doc xmlns='one_two' />"}, | ||
219 | - {XML_STATUS_ERROR, "<doc xmlns='one
two' />"}, | ||
220 | + {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')}, | ||
221 | + {XML_STATUS_ERROR, "<doc xmlns='one
two' />", XCS('\n')}, | ||
222 | + {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')}, | ||
223 | }; | ||
224 | |||
225 | size_t i = 0; | ||
226 | size_t failCount = 0; | ||
227 | for (; i < sizeof(cases) / sizeof(cases[0]); i++) { | ||
228 | - XML_Parser parser = XML_ParserCreateNS(NULL, '\n'); | ||
229 | + XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep); | ||
230 | XML_SetElementHandler(parser, dummy_start_element, dummy_end_element); | ||
231 | if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc), | ||
232 | /*isFinal*/ XML_TRUE) | ||
diff --git a/meta/recipes-core/expat/expat_2.2.10.bb b/meta/recipes-core/expat/expat_2.2.10.bb index 08e8ff1cea..f99fa7edb6 100644 --- a/meta/recipes-core/expat/expat_2.2.10.bb +++ b/meta/recipes-core/expat/expat_2.2.10.bb | |||
@@ -10,9 +10,17 @@ VERSION_TAG = "${@d.getVar('PV').replace('.', '_')}" | |||
10 | 10 | ||
11 | SRC_URI = "https://github.com/libexpat/libexpat/releases/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \ | 11 | SRC_URI = "https://github.com/libexpat/libexpat/releases/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \ |
12 | file://libtool-tag.patch \ | 12 | file://libtool-tag.patch \ |
13 | file://run-ptest \ | 13 | file://run-ptest \ |
14 | file://0001-Add-output-of-tests-result.patch \ | 14 | file://0001-Add-output-of-tests-result.patch \ |
15 | " | 15 | file://CVE-2022-22822-27.patch \ |
16 | file://CVE-2021-45960.patch \ | ||
17 | file://CVE-2021-46143.patch \ | ||
18 | file://CVE-2022-23852.patch \ | ||
19 | file://CVE-2022-23990.patch \ | ||
20 | file://CVE-2022-25235.patch \ | ||
21 | file://CVE-2022-25236-1.patch \ | ||
22 | file://CVE-2022-25236-2.patch \ | ||
23 | " | ||
16 | 24 | ||
17 | UPSTREAM_CHECK_URI = "https://github.com/libexpat/libexpat/releases/" | 25 | UPSTREAM_CHECK_URI = "https://github.com/libexpat/libexpat/releases/" |
18 | 26 | ||