diff options
Diffstat (limited to 'meta/recipes-graphics/harfbuzz')
4 files changed, 653 insertions, 1 deletions
diff --git a/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193-pre0.patch b/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193-pre0.patch new file mode 100644 index 0000000000..90d4cfefb4 --- /dev/null +++ b/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193-pre0.patch | |||
@@ -0,0 +1,335 @@ | |||
1 | From 3122c2cdc45a964efedad8953a2df67205c3e3a8 Mon Sep 17 00:00:00 2001 | ||
2 | From: Behdad Esfahbod <behdad@behdad.org> | ||
3 | Date: Sat, 4 Dec 2021 19:50:33 -0800 | ||
4 | Subject: [PATCH] [buffer] Add HB_GLYPH_FLAG_UNSAFE_TO_CONCAT | ||
5 | |||
6 | Fixes https://github.com/harfbuzz/harfbuzz/issues/1463 | ||
7 | Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/3122c2cdc45a964efedad8953a2df67205c3e3a8] | ||
8 | Comment1: To backport the fix for CVE-2023-25193, add defination for HB_GLYPH_FLAG_UNSAFE_TO_CONCAT. This patch is needed along with CVE-2023-25193-pre1.patch for sucessfull porting. | ||
9 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
10 | --- | ||
11 | src/hb-buffer.cc | 10 ++--- | ||
12 | src/hb-buffer.h | 76 ++++++++++++++++++++++++++++++------ | ||
13 | src/hb-buffer.hh | 33 ++++++++++------ | ||
14 | src/hb-ot-layout-gsubgpos.hh | 39 +++++++++++++++--- | ||
15 | src/hb-ot-shape.cc | 8 +--- | ||
16 | 5 files changed, 124 insertions(+), 42 deletions(-) | ||
17 | |||
18 | diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc | ||
19 | index 6131c86..bba5eae 100644 | ||
20 | --- a/src/hb-buffer.cc | ||
21 | +++ b/src/hb-buffer.cc | ||
22 | @@ -610,14 +610,14 @@ done: | ||
23 | } | ||
24 | |||
25 | void | ||
26 | -hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end) | ||
27 | +hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end, hb_mask_t mask) | ||
28 | { | ||
29 | unsigned int cluster = (unsigned int) -1; | ||
30 | cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster); | ||
31 | - _unsafe_to_break_set_mask (info, start, end, cluster); | ||
32 | + _unsafe_to_break_set_mask (info, start, end, cluster, mask); | ||
33 | } | ||
34 | void | ||
35 | -hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end) | ||
36 | +hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end, hb_mask_t mask) | ||
37 | { | ||
38 | if (!have_output) | ||
39 | { | ||
40 | @@ -631,8 +631,8 @@ hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int en | ||
41 | unsigned int cluster = (unsigned int) -1; | ||
42 | cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster); | ||
43 | cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster); | ||
44 | - _unsafe_to_break_set_mask (out_info, start, out_len, cluster); | ||
45 | - _unsafe_to_break_set_mask (info, idx, end, cluster); | ||
46 | + _unsafe_to_break_set_mask (out_info, start, out_len, cluster, mask); | ||
47 | + _unsafe_to_break_set_mask (info, idx, end, cluster, mask); | ||
48 | } | ||
49 | |||
50 | void | ||
51 | diff --git a/src/hb-buffer.h b/src/hb-buffer.h | ||
52 | index d5cb746..42dc92a 100644 | ||
53 | --- a/src/hb-buffer.h | ||
54 | +++ b/src/hb-buffer.h | ||
55 | @@ -77,26 +77,76 @@ typedef struct hb_glyph_info_t | ||
56 | * @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the | ||
57 | * beginning of the cluster this glyph is part of, | ||
58 | * then both sides need to be re-shaped, as the | ||
59 | - * result might be different. On the flip side, | ||
60 | - * it means that when this flag is not present, | ||
61 | - * then it's safe to break the glyph-run at the | ||
62 | - * beginning of this cluster, and the two sides | ||
63 | - * represent the exact same result one would get | ||
64 | - * if breaking input text at the beginning of | ||
65 | - * this cluster and shaping the two sides | ||
66 | - * separately. This can be used to optimize | ||
67 | - * paragraph layout, by avoiding re-shaping | ||
68 | - * of each line after line-breaking, or limiting | ||
69 | - * the reshaping to a small piece around the | ||
70 | - * breaking point only. | ||
71 | + * result might be different. | ||
72 | + * | ||
73 | + * On the flip side, it means that when this | ||
74 | + * flag is not present, then it is safe to break | ||
75 | + * the glyph-run at the beginning of this | ||
76 | + * cluster, and the two sides will represent the | ||
77 | + * exact same result one would get if breaking | ||
78 | + * input text at the beginning of this cluster | ||
79 | + * and shaping the two sides separately. | ||
80 | + * | ||
81 | + * This can be used to optimize paragraph | ||
82 | + * layout, by avoiding re-shaping of each line | ||
83 | + * after line-breaking. | ||
84 | + * | ||
85 | + * @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT: Indicates that if input text is changed on one | ||
86 | + * side of the beginning of the cluster this glyph | ||
87 | + * is part of, then the shaping results for the | ||
88 | + * other side might change. | ||
89 | + * | ||
90 | + * Note that the absence of this flag will NOT by | ||
91 | + * itself mean that it IS safe to concat text. | ||
92 | + * Only two pieces of text both of which clear of | ||
93 | + * this flag can be concatenated safely. | ||
94 | + * | ||
95 | + * This can be used to optimize paragraph | ||
96 | + * layout, by avoiding re-shaping of each line | ||
97 | + * after line-breaking, by limiting the | ||
98 | + * reshaping to a small piece around the | ||
99 | + * breaking positin only, even if the breaking | ||
100 | + * position carries the | ||
101 | + * #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when | ||
102 | + * hyphenation or other text transformation | ||
103 | + * happens at line-break position, in the following | ||
104 | + * way: | ||
105 | + * | ||
106 | + * 1. Iterate back from the line-break position till | ||
107 | + * the the first cluster start position that is | ||
108 | + * NOT unsafe-to-concat, 2. shape the segment from | ||
109 | + * there till the end of line, 3. check whether the | ||
110 | + * resulting glyph-run also is clear of the | ||
111 | + * unsafe-to-concat at its start-of-text position; | ||
112 | + * if it is, just splice it into place and the line | ||
113 | + * is shaped; If not, move on to a position further | ||
114 | + * back that is clear of unsafe-to-concat and retry | ||
115 | + * from there, and repeat. | ||
116 | + * | ||
117 | + * At the start of next line a similar algorithm can | ||
118 | + * be implemented. A slight complication will arise, | ||
119 | + * because while our buffer API has a way to | ||
120 | + * return flags for position corresponding to | ||
121 | + * start-of-text, there is currently no position | ||
122 | + * corresponding to end-of-text. This limitation | ||
123 | + * can be alleviated by shaping more text than needed | ||
124 | + * and looking for unsafe-to-concat flag within text | ||
125 | + * clusters. | ||
126 | + * | ||
127 | + * The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will | ||
128 | + * always imply this flag. | ||
129 | + * | ||
130 | + * Since: REPLACEME | ||
131 | + * | ||
132 | * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. | ||
133 | * | ||
134 | * Since: 1.5.0 | ||
135 | */ | ||
136 | typedef enum { /*< flags >*/ | ||
137 | HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, | ||
138 | + HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002, | ||
139 | |||
140 | - HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */ | ||
141 | + HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */ | ||
142 | } hb_glyph_flags_t; | ||
143 | |||
144 | HB_EXTERN hb_glyph_flags_t | ||
145 | diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh | ||
146 | index b5596d9..beac7b6 100644 | ||
147 | --- a/src/hb-buffer.hh | ||
148 | +++ b/src/hb-buffer.hh | ||
149 | @@ -67,8 +67,8 @@ enum hb_buffer_scratch_flags_t { | ||
150 | HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, | ||
151 | HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, | ||
152 | HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u, | ||
153 | - HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u, | ||
154 | - HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u, | ||
155 | + HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u, | ||
156 | + HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u, | ||
157 | |||
158 | /* Reserved for complex shapers' internal use. */ | ||
159 | HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, | ||
160 | @@ -324,8 +324,19 @@ struct hb_buffer_t | ||
161 | return; | ||
162 | unsafe_to_break_impl (start, end); | ||
163 | } | ||
164 | - HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end); | ||
165 | - HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end); | ||
166 | + void unsafe_to_concat (unsigned int start, | ||
167 | + unsigned int end) | ||
168 | + { | ||
169 | + if (end - start < 2) | ||
170 | + return; | ||
171 | + unsafe_to_break_impl (start, end, HB_GLYPH_FLAG_UNSAFE_TO_CONCAT); | ||
172 | + } | ||
173 | + HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end, | ||
174 | + hb_mask_t mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT); | ||
175 | + HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end, | ||
176 | + hb_mask_t mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT); | ||
177 | + void unsafe_to_concat_from_outbuffer (unsigned int start, unsigned int end) | ||
178 | + { unsafe_to_break_from_outbuffer (start, end, HB_GLYPH_FLAG_UNSAFE_TO_CONCAT); } | ||
179 | |||
180 | |||
181 | /* Internal methods */ | ||
182 | @@ -377,12 +388,7 @@ struct hb_buffer_t | ||
183 | set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0) | ||
184 | { | ||
185 | if (inf.cluster != cluster) | ||
186 | - { | ||
187 | - if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) | ||
188 | - inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; | ||
189 | - else | ||
190 | - inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; | ||
191 | - } | ||
192 | + inf.mask = (inf.mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED); | ||
193 | inf.cluster = cluster; | ||
194 | } | ||
195 | |||
196 | @@ -398,13 +404,14 @@ struct hb_buffer_t | ||
197 | void | ||
198 | _unsafe_to_break_set_mask (hb_glyph_info_t *infos, | ||
199 | unsigned int start, unsigned int end, | ||
200 | - unsigned int cluster) | ||
201 | + unsigned int cluster, | ||
202 | + hb_mask_t mask) | ||
203 | { | ||
204 | for (unsigned int i = start; i < end; i++) | ||
205 | if (cluster != infos[i].cluster) | ||
206 | { | ||
207 | - scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK; | ||
208 | - infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; | ||
209 | + scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS; | ||
210 | + infos[i].mask |= mask; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh | ||
215 | index 579d178..a6ca456 100644 | ||
216 | --- a/src/hb-ot-layout-gsubgpos.hh | ||
217 | +++ b/src/hb-ot-layout-gsubgpos.hh | ||
218 | @@ -369,7 +369,7 @@ struct hb_ot_apply_context_t : | ||
219 | may_skip (const hb_glyph_info_t &info) const | ||
220 | { return matcher.may_skip (c, info); } | ||
221 | |||
222 | - bool next () | ||
223 | + bool next (unsigned *unsafe_to = nullptr) | ||
224 | { | ||
225 | assert (num_items > 0); | ||
226 | while (idx + num_items < end) | ||
227 | @@ -392,11 +392,17 @@ struct hb_ot_apply_context_t : | ||
228 | } | ||
229 | |||
230 | if (skip == matcher_t::SKIP_NO) | ||
231 | + { | ||
232 | + if (unsafe_to) | ||
233 | + *unsafe_to = idx + 1; | ||
234 | return false; | ||
235 | + } | ||
236 | } | ||
237 | + if (unsafe_to) | ||
238 | + *unsafe_to = end; | ||
239 | return false; | ||
240 | } | ||
241 | - bool prev () | ||
242 | + bool prev (unsigned *unsafe_from = nullptr) | ||
243 | { | ||
244 | assert (num_items > 0); | ||
245 | while (idx > num_items - 1) | ||
246 | @@ -419,8 +425,14 @@ struct hb_ot_apply_context_t : | ||
247 | } | ||
248 | |||
249 | if (skip == matcher_t::SKIP_NO) | ||
250 | + { | ||
251 | + if (unsafe_from) | ||
252 | + *unsafe_from = hb_max (1u, idx) - 1u; | ||
253 | return false; | ||
254 | + } | ||
255 | } | ||
256 | + if (unsafe_from) | ||
257 | + *unsafe_from = 0; | ||
258 | return false; | ||
259 | } | ||
260 | |||
261 | @@ -834,7 +846,12 @@ static inline bool match_input (hb_ot_apply_context_t *c, | ||
262 | match_positions[0] = buffer->idx; | ||
263 | for (unsigned int i = 1; i < count; i++) | ||
264 | { | ||
265 | - if (!skippy_iter.next ()) return_trace (false); | ||
266 | + unsigned unsafe_to; | ||
267 | + if (!skippy_iter.next (&unsafe_to)) | ||
268 | + { | ||
269 | + c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to); | ||
270 | + return_trace (false); | ||
271 | + } | ||
272 | |||
273 | match_positions[i] = skippy_iter.idx; | ||
274 | |||
275 | @@ -1022,8 +1039,14 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c, | ||
276 | skippy_iter.set_match_func (match_func, match_data, backtrack); | ||
277 | |||
278 | for (unsigned int i = 0; i < count; i++) | ||
279 | - if (!skippy_iter.prev ()) | ||
280 | + { | ||
281 | + unsigned unsafe_from; | ||
282 | + if (!skippy_iter.prev (&unsafe_from)) | ||
283 | + { | ||
284 | + c->buffer->unsafe_to_concat_from_outbuffer (unsafe_from, c->buffer->idx); | ||
285 | return_trace (false); | ||
286 | + } | ||
287 | + } | ||
288 | |||
289 | *match_start = skippy_iter.idx; | ||
290 | |||
291 | @@ -1045,8 +1068,14 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c, | ||
292 | skippy_iter.set_match_func (match_func, match_data, lookahead); | ||
293 | |||
294 | for (unsigned int i = 0; i < count; i++) | ||
295 | - if (!skippy_iter.next ()) | ||
296 | + { | ||
297 | + unsigned unsafe_to; | ||
298 | + if (!skippy_iter.next (&unsafe_to)) | ||
299 | + { | ||
300 | + c->buffer->unsafe_to_concat (c->buffer->idx + offset, unsafe_to); | ||
301 | return_trace (false); | ||
302 | + } | ||
303 | + } | ||
304 | |||
305 | *end_index = skippy_iter.idx + 1; | ||
306 | |||
307 | diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc | ||
308 | index 5d9a70c..5d10b30 100644 | ||
309 | --- a/src/hb-ot-shape.cc | ||
310 | +++ b/src/hb-ot-shape.cc | ||
311 | @@ -1008,7 +1008,7 @@ hb_propagate_flags (hb_buffer_t *buffer) | ||
312 | /* Propagate cluster-level glyph flags to be the same on all cluster glyphs. | ||
313 | * Simplifies using them. */ | ||
314 | |||
315 | - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK)) | ||
316 | + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS)) | ||
317 | return; | ||
318 | |||
319 | hb_glyph_info_t *info = buffer->info; | ||
320 | @@ -1017,11 +1017,7 @@ hb_propagate_flags (hb_buffer_t *buffer) | ||
321 | { | ||
322 | unsigned int mask = 0; | ||
323 | for (unsigned int i = start; i < end; i++) | ||
324 | - if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) | ||
325 | - { | ||
326 | - mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; | ||
327 | - break; | ||
328 | - } | ||
329 | + mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED; | ||
330 | if (mask) | ||
331 | for (unsigned int i = start; i < end; i++) | ||
332 | info[i].mask |= mask; | ||
333 | -- | ||
334 | 2.25.1 | ||
335 | |||
diff --git a/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193-pre1.patch b/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193-pre1.patch new file mode 100644 index 0000000000..4994e0ef68 --- /dev/null +++ b/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193-pre1.patch | |||
@@ -0,0 +1,135 @@ | |||
1 | From b29fbd16fa82b82bdf0dcb2f13a63f7dc23cf324 Mon Sep 17 00:00:00 2001 | ||
2 | From: Behdad Esfahbod <behdad@behdad.org> | ||
3 | Date: Mon, 6 Feb 2023 13:08:52 -0700 | ||
4 | Subject: [PATCH] [gsubgpos] Refactor skippy_iter.match() | ||
5 | |||
6 | Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/b29fbd16fa82b82bdf0dcb2f13a63f7dc23cf324] | ||
7 | Comment1: To backport the fix for CVE-2023-25193, add defination for MATCH, NOT_MATCH and SKIP. | ||
8 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
9 | --- | ||
10 | src/hb-ot-layout-gsubgpos.hh | 94 +++++++++++++++++++++--------------- | ||
11 | 1 file changed, 54 insertions(+), 40 deletions(-) | ||
12 | |||
13 | diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh | ||
14 | index a6ca456..5a7e564 100644 | ||
15 | --- a/src/hb-ot-layout-gsubgpos.hh | ||
16 | +++ b/src/hb-ot-layout-gsubgpos.hh | ||
17 | @@ -369,33 +369,52 @@ struct hb_ot_apply_context_t : | ||
18 | may_skip (const hb_glyph_info_t &info) const | ||
19 | { return matcher.may_skip (c, info); } | ||
20 | |||
21 | + enum match_t { | ||
22 | + MATCH, | ||
23 | + NOT_MATCH, | ||
24 | + SKIP | ||
25 | + }; | ||
26 | + | ||
27 | + match_t match (hb_glyph_info_t &info) | ||
28 | + { | ||
29 | + matcher_t::may_skip_t skip = matcher.may_skip (c, info); | ||
30 | + if (unlikely (skip == matcher_t::SKIP_YES)) | ||
31 | + return SKIP; | ||
32 | + | ||
33 | + matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data); | ||
34 | + if (match == matcher_t::MATCH_YES || | ||
35 | + (match == matcher_t::MATCH_MAYBE && | ||
36 | + skip == matcher_t::SKIP_NO)) | ||
37 | + return MATCH; | ||
38 | + | ||
39 | + if (skip == matcher_t::SKIP_NO) | ||
40 | + return NOT_MATCH; | ||
41 | + | ||
42 | + return SKIP; | ||
43 | + } | ||
44 | + | ||
45 | bool next (unsigned *unsafe_to = nullptr) | ||
46 | { | ||
47 | assert (num_items > 0); | ||
48 | while (idx + num_items < end) | ||
49 | { | ||
50 | idx++; | ||
51 | - const hb_glyph_info_t &info = c->buffer->info[idx]; | ||
52 | - | ||
53 | - matcher_t::may_skip_t skip = matcher.may_skip (c, info); | ||
54 | - if (unlikely (skip == matcher_t::SKIP_YES)) | ||
55 | - continue; | ||
56 | - | ||
57 | - matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data); | ||
58 | - if (match == matcher_t::MATCH_YES || | ||
59 | - (match == matcher_t::MATCH_MAYBE && | ||
60 | - skip == matcher_t::SKIP_NO)) | ||
61 | - { | ||
62 | - num_items--; | ||
63 | - if (match_glyph_data) match_glyph_data++; | ||
64 | - return true; | ||
65 | - } | ||
66 | - | ||
67 | - if (skip == matcher_t::SKIP_NO) | ||
68 | + switch (match (c->buffer->info[idx])) | ||
69 | { | ||
70 | - if (unsafe_to) | ||
71 | - *unsafe_to = idx + 1; | ||
72 | - return false; | ||
73 | + case MATCH: | ||
74 | + { | ||
75 | + num_items--; | ||
76 | + if (match_glyph_data) match_glyph_data++; | ||
77 | + return true; | ||
78 | + } | ||
79 | + case NOT_MATCH: | ||
80 | + { | ||
81 | + if (unsafe_to) | ||
82 | + *unsafe_to = idx + 1; | ||
83 | + return false; | ||
84 | + } | ||
85 | + case SKIP: | ||
86 | + continue; | ||
87 | } | ||
88 | } | ||
89 | if (unsafe_to) | ||
90 | @@ -408,27 +427,22 @@ struct hb_ot_apply_context_t : | ||
91 | while (idx > num_items - 1) | ||
92 | { | ||
93 | idx--; | ||
94 | - const hb_glyph_info_t &info = c->buffer->out_info[idx]; | ||
95 | - | ||
96 | - matcher_t::may_skip_t skip = matcher.may_skip (c, info); | ||
97 | - if (unlikely (skip == matcher_t::SKIP_YES)) | ||
98 | - continue; | ||
99 | - | ||
100 | - matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data); | ||
101 | - if (match == matcher_t::MATCH_YES || | ||
102 | - (match == matcher_t::MATCH_MAYBE && | ||
103 | - skip == matcher_t::SKIP_NO)) | ||
104 | + switch (match (c->buffer->out_info[idx])) | ||
105 | { | ||
106 | - num_items--; | ||
107 | - if (match_glyph_data) match_glyph_data++; | ||
108 | - return true; | ||
109 | - } | ||
110 | - | ||
111 | - if (skip == matcher_t::SKIP_NO) | ||
112 | - { | ||
113 | - if (unsafe_from) | ||
114 | - *unsafe_from = hb_max (1u, idx) - 1u; | ||
115 | - return false; | ||
116 | + case MATCH: | ||
117 | + { | ||
118 | + num_items--; | ||
119 | + if (match_glyph_data) match_glyph_data++; | ||
120 | + return true; | ||
121 | + } | ||
122 | + case NOT_MATCH: | ||
123 | + { | ||
124 | + if (unsafe_from) | ||
125 | + *unsafe_from = hb_max (1u, idx) - 1u; | ||
126 | + return false; | ||
127 | + } | ||
128 | + case SKIP: | ||
129 | + continue; | ||
130 | } | ||
131 | } | ||
132 | if (unsafe_from) | ||
133 | -- | ||
134 | 2.25.1 | ||
135 | |||
diff --git a/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193.patch b/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193.patch new file mode 100644 index 0000000000..e4ac13dbad --- /dev/null +++ b/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193.patch | |||
@@ -0,0 +1,179 @@ | |||
1 | From 9c8e972dbecda93546038d24444d8216397d75a3 Mon Sep 17 00:00:00 2001 | ||
2 | From: Behdad Esfahbod <behdad@behdad.org> | ||
3 | Date: Mon, 6 Feb 2023 14:51:25 -0700 | ||
4 | Subject: [PATCH] [GPOS] Avoid O(n^2) behavior in mark-attachment | ||
5 | |||
6 | Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/8708b9e081192786c027bb7f5f23d76dbe5c19e8] | ||
7 | Comment1: The Original Patch [https://github.com/harfbuzz/harfbuzz/commit/85be877925ddbf34f74a1229f3ca1716bb6170dc] causes regression and was reverted. This Patch completes the fix. | ||
8 | Comment2: The Patch contained files MarkBasePosFormat1.hh and MarkLigPosFormat1.hh which were moved from hb-ot-layout-gpos-table.hh as per https://github.com/harfbuzz/harfbuzz/commit/197d9a5c994eb41c8c89b7b958b26b1eacfeeb00 | ||
9 | CVE: CVE-2023-25193 | ||
10 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
11 | Signed-off-by: Dhairya Nagodra <dnagodra@cisco.com> | ||
12 | |||
13 | --- | ||
14 | src/hb-ot-layout-gpos-table.hh | 103 +++++++++++++++++++++++---------- | ||
15 | src/hb-ot-layout-gsubgpos.hh | 5 +- | ||
16 | 2 files changed, 78 insertions(+), 30 deletions(-) | ||
17 | |||
18 | diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh | ||
19 | index 024312d..db5f9ae 100644 | ||
20 | --- a/src/hb-ot-layout-gpos-table.hh | ||
21 | +++ b/src/hb-ot-layout-gpos-table.hh | ||
22 | @@ -1458,6 +1458,25 @@ struct MarkBasePosFormat1 | ||
23 | |||
24 | const Coverage &get_coverage () const { return this+markCoverage; } | ||
25 | |||
26 | + static inline bool accept (hb_buffer_t *buffer, unsigned idx) | ||
27 | + { | ||
28 | + /* We only want to attach to the first of a MultipleSubst sequence. | ||
29 | + * https://github.com/harfbuzz/harfbuzz/issues/740 | ||
30 | + * Reject others... | ||
31 | + * ...but stop if we find a mark in the MultipleSubst sequence: | ||
32 | + * https://github.com/harfbuzz/harfbuzz/issues/1020 */ | ||
33 | + return !_hb_glyph_info_multiplied (&buffer->info[idx]) || | ||
34 | + 0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) || | ||
35 | + (idx == 0 || | ||
36 | + _hb_glyph_info_is_mark (&buffer->info[idx - 1]) || | ||
37 | + !_hb_glyph_info_multiplied (&buffer->info[idx - 1]) || | ||
38 | + _hb_glyph_info_get_lig_id (&buffer->info[idx]) != | ||
39 | + _hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) || | ||
40 | + _hb_glyph_info_get_lig_comp (&buffer->info[idx]) != | ||
41 | + _hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1 | ||
42 | + ); | ||
43 | + } | ||
44 | + | ||
45 | bool apply (hb_ot_apply_context_t *c) const | ||
46 | { | ||
47 | TRACE_APPLY (this); | ||
48 | @@ -1465,37 +1484,46 @@ struct MarkBasePosFormat1 | ||
49 | unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); | ||
50 | if (likely (mark_index == NOT_COVERED)) return_trace (false); | ||
51 | |||
52 | - /* Now we search backwards for a non-mark glyph */ | ||
53 | + /* Now we search backwards for a non-mark glyph. | ||
54 | + * We don't use skippy_iter.prev() to avoid O(n^2) behavior. */ | ||
55 | + | ||
56 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; | ||
57 | - skippy_iter.reset (buffer->idx, 1); | ||
58 | skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); | ||
59 | - do { | ||
60 | - if (!skippy_iter.prev ()) return_trace (false); | ||
61 | - /* We only want to attach to the first of a MultipleSubst sequence. | ||
62 | - * https://github.com/harfbuzz/harfbuzz/issues/740 | ||
63 | - * Reject others... | ||
64 | - * ...but stop if we find a mark in the MultipleSubst sequence: | ||
65 | - * https://github.com/harfbuzz/harfbuzz/issues/1020 */ | ||
66 | - if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) || | ||
67 | - 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) || | ||
68 | - (skippy_iter.idx == 0 || | ||
69 | - _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) || | ||
70 | - _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) != | ||
71 | - _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) || | ||
72 | - _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) != | ||
73 | - _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1 | ||
74 | - )) | ||
75 | - break; | ||
76 | - skippy_iter.reject (); | ||
77 | - } while (true); | ||
78 | + unsigned j; | ||
79 | + for (j = buffer->idx; j > c->last_base_until; j--) | ||
80 | + { | ||
81 | + auto match = skippy_iter.match (buffer->info[j - 1]); | ||
82 | + if (match == skippy_iter.MATCH) | ||
83 | + { | ||
84 | + if (!accept (buffer, j - 1)) | ||
85 | + match = skippy_iter.SKIP; | ||
86 | + } | ||
87 | + if (match == skippy_iter.MATCH) | ||
88 | + { | ||
89 | + c->last_base = (signed) j - 1; | ||
90 | + break; | ||
91 | + } | ||
92 | + } | ||
93 | + c->last_base_until = buffer->idx; | ||
94 | + if (c->last_base == -1) | ||
95 | + { | ||
96 | + buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1); | ||
97 | + return_trace (false); | ||
98 | + } | ||
99 | + | ||
100 | + unsigned idx = (unsigned) c->last_base; | ||
101 | |||
102 | /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ | ||
103 | - //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); } | ||
104 | + //if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); } | ||
105 | |||
106 | - unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); | ||
107 | - if (base_index == NOT_COVERED) return_trace (false); | ||
108 | + unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint); | ||
109 | + if (base_index == NOT_COVERED) | ||
110 | + { | ||
111 | + buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1); | ||
112 | + return_trace (false); | ||
113 | + } | ||
114 | |||
115 | - return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); | ||
116 | + return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx)); | ||
117 | } | ||
118 | |||
119 | bool subset (hb_subset_context_t *c) const | ||
120 | @@ -1587,15 +1615,32 @@ struct MarkLigPosFormat1 | ||
121 | if (likely (mark_index == NOT_COVERED)) return_trace (false); | ||
122 | |||
123 | /* Now we search backwards for a non-mark glyph */ | ||
124 | + | ||
125 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; | ||
126 | - skippy_iter.reset (buffer->idx, 1); | ||
127 | skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); | ||
128 | - if (!skippy_iter.prev ()) return_trace (false); | ||
129 | + | ||
130 | + unsigned j; | ||
131 | + for (j = buffer->idx; j > c->last_base_until; j--) | ||
132 | + { | ||
133 | + auto match = skippy_iter.match (buffer->info[j - 1]); | ||
134 | + if (match == skippy_iter.MATCH) | ||
135 | + { | ||
136 | + c->last_base = (signed) j - 1; | ||
137 | + break; | ||
138 | + } | ||
139 | + } | ||
140 | + c->last_base_until = buffer->idx; | ||
141 | + if (c->last_base == -1) | ||
142 | + { | ||
143 | + buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1); | ||
144 | + return_trace (false); | ||
145 | + } | ||
146 | + | ||
147 | + j = (unsigned) c->last_base; | ||
148 | |||
149 | /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ | ||
150 | - //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); } | ||
151 | + //if (!_hb_glyph_info_is_ligature (&buffer->info[idx])) { return_trace (false); } | ||
152 | |||
153 | - unsigned int j = skippy_iter.idx; | ||
154 | unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); | ||
155 | if (lig_index == NOT_COVERED) return_trace (false); | ||
156 | |||
157 | diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh | ||
158 | index 5a7e564..437123c 100644 | ||
159 | --- a/src/hb-ot-layout-gsubgpos.hh | ||
160 | +++ b/src/hb-ot-layout-gsubgpos.hh | ||
161 | @@ -503,6 +503,9 @@ struct hb_ot_apply_context_t : | ||
162 | uint32_t random_state; | ||
163 | |||
164 | |||
165 | + signed last_base = -1; // GPOS uses | ||
166 | + unsigned last_base_until = 0; // GPOS uses | ||
167 | + | ||
168 | hb_ot_apply_context_t (unsigned int table_index_, | ||
169 | hb_font_t *font_, | ||
170 | hb_buffer_t *buffer_) : | ||
171 | @@ -536,7 +539,7 @@ struct hb_ot_apply_context_t : | ||
172 | iter_context.init (this, true); | ||
173 | } | ||
174 | |||
175 | - void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); } | ||
176 | + void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; last_base = -1; last_base_until = 0; init_iters (); } | ||
177 | void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); } | ||
178 | void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); } | ||
179 | void set_random (bool random_) { random = random_; } | ||
diff --git a/meta/recipes-graphics/harfbuzz/harfbuzz_2.6.4.bb b/meta/recipes-graphics/harfbuzz/harfbuzz_2.6.4.bb index ee08c12bee..0cfe01f1e5 100644 --- a/meta/recipes-graphics/harfbuzz/harfbuzz_2.6.4.bb +++ b/meta/recipes-graphics/harfbuzz/harfbuzz_2.6.4.bb | |||
@@ -7,7 +7,10 @@ LICENSE = "MIT" | |||
7 | LIC_FILES_CHKSUM = "file://COPYING;md5=e11f5c3149cdec4bb309babb020b32b9 \ | 7 | LIC_FILES_CHKSUM = "file://COPYING;md5=e11f5c3149cdec4bb309babb020b32b9 \ |
8 | file://src/hb-ucd.cc;beginline=1;endline=15;md5=29d4dcb6410429195df67efe3382d8bc" | 8 | file://src/hb-ucd.cc;beginline=1;endline=15;md5=29d4dcb6410429195df67efe3382d8bc" |
9 | 9 | ||
10 | SRC_URI = "http://www.freedesktop.org/software/harfbuzz/release/${BP}.tar.xz" | 10 | SRC_URI = "http://www.freedesktop.org/software/harfbuzz/release/${BP}.tar.xz \ |
11 | file://CVE-2023-25193-pre0.patch \ | ||
12 | file://CVE-2023-25193-pre1.patch \ | ||
13 | file://CVE-2023-25193.patch" | ||
11 | SRC_URI[md5sum] = "2b3a4dfdb3e5e50055f941978944da9f" | 14 | SRC_URI[md5sum] = "2b3a4dfdb3e5e50055f941978944da9f" |
12 | SRC_URI[sha256sum] = "9413b8d96132d699687ef914ebb8c50440efc87b3f775d25856d7ec347c03c12" | 15 | SRC_URI[sha256sum] = "9413b8d96132d699687ef914ebb8c50440efc87b3f775d25856d7ec347c03c12" |
13 | 16 | ||