diff options
author | Siddharth <sdoshi@mvista.com> | 2023-03-11 16:54:13 +0530 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-03-21 14:26:31 +0000 |
commit | e0b2ca58679f610d01fb8a99e656e4b812c69418 (patch) | |
tree | 33e7bb7784c514c548316905a09f21d6cf579dff | |
parent | 830eb878166d531d9188176ae40a25c54a309e6c (diff) | |
download | poky-e0b2ca58679f610d01fb8a99e656e4b812c69418.tar.gz |
harfbuzz: Security fix for CVE-2023-25193
Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/8708b9e081192786c027bb7f5f23d76dbe5c19e8]
(From OE-Core rev: cadcb982dbeb1489affe4e594d4b84386f6cd4fe)
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
3 files changed, 329 insertions, 0 deletions
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..47d2d7c270 --- /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 c77ec12..04b823e 100644 | ||
15 | --- a/src/hb-ot-layout-gsubgpos.hh | ||
16 | +++ b/src/hb-ot-layout-gsubgpos.hh | ||
17 | @@ -532,33 +532,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, get_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 | - 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, get_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 | - advance_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 | + advance_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 | @@ -571,27 +590,22 @@ struct hb_ot_apply_context_t : | ||
91 | while (idx > num_items - 1) | ||
92 | { | ||
93 | idx--; | ||
94 | - 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, get_glyph_data ()); | ||
101 | - if (match == matcher_t::MATCH_YES || | ||
102 | - (match == matcher_t::MATCH_MAYBE && | ||
103 | - skip == matcher_t::SKIP_NO)) | ||
104 | - { | ||
105 | - num_items--; | ||
106 | - advance_glyph_data (); | ||
107 | - return true; | ||
108 | - } | ||
109 | - | ||
110 | - if (skip == matcher_t::SKIP_NO) | ||
111 | + switch (match (c->buffer->out_info[idx])) | ||
112 | { | ||
113 | - if (unsafe_from) | ||
114 | - *unsafe_from = hb_max (1u, idx) - 1u; | ||
115 | - return false; | ||
116 | + case MATCH: | ||
117 | + { | ||
118 | + num_items--; | ||
119 | + advance_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..f5c5cf439d --- /dev/null +++ b/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193.patch | |||
@@ -0,0 +1,192 @@ | |||
1 | From 8708b9e081192786c027bb7f5f23d76dbe5c19e8 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 | CVE: CVE-2023-25193 | ||
9 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
10 | |||
11 | --- | ||
12 | src/OT/Layout/GPOS/MarkBasePosFormat1.hh | 76 +++++++++++++++--------- | ||
13 | src/OT/Layout/GPOS/MarkLigPosFormat1.hh | 24 ++++++-- | ||
14 | src/hb-ot-layout-gsubgpos.hh | 5 +- | ||
15 | 3 files changed, 69 insertions(+), 36 deletions(-) | ||
16 | |||
17 | diff --git a/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/src/OT/Layout/GPOS/MarkBasePosFormat1.hh | ||
18 | index ebb8c31..73839a4 100644 | ||
19 | --- a/src/OT/Layout/GPOS/MarkBasePosFormat1.hh | ||
20 | +++ b/src/OT/Layout/GPOS/MarkBasePosFormat1.hh | ||
21 | @@ -90,6 +90,25 @@ struct MarkBasePosFormat1_2 | ||
22 | |||
23 | const Coverage &get_coverage () const { return this+markCoverage; } | ||
24 | |||
25 | + static inline bool accept (hb_buffer_t *buffer, unsigned idx) | ||
26 | + { | ||
27 | + /* We only want to attach to the first of a MultipleSubst sequence. | ||
28 | + * https://github.com/harfbuzz/harfbuzz/issues/740 | ||
29 | + * Reject others... | ||
30 | + * ...but stop if we find a mark in the MultipleSubst sequence: | ||
31 | + * https://github.com/harfbuzz/harfbuzz/issues/1020 */ | ||
32 | + return !_hb_glyph_info_multiplied (&buffer->info[idx]) || | ||
33 | + 0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) || | ||
34 | + (idx == 0 || | ||
35 | + _hb_glyph_info_is_mark (&buffer->info[idx - 1]) || | ||
36 | + !_hb_glyph_info_multiplied (&buffer->info[idx - 1]) || | ||
37 | + _hb_glyph_info_get_lig_id (&buffer->info[idx]) != | ||
38 | + _hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) || | ||
39 | + _hb_glyph_info_get_lig_comp (&buffer->info[idx]) != | ||
40 | + _hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1 | ||
41 | + ); | ||
42 | + } | ||
43 | + | ||
44 | bool apply (hb_ot_apply_context_t *c) const | ||
45 | { | ||
46 | TRACE_APPLY (this); | ||
47 | @@ -97,48 +116,47 @@ struct MarkBasePosFormat1_2 | ||
48 | unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); | ||
49 | if (likely (mark_index == NOT_COVERED)) return_trace (false); | ||
50 | |||
51 | - /* Now we search backwards for a non-mark glyph */ | ||
52 | + /* Now we search backwards for a non-mark glyph. | ||
53 | + * We don't use skippy_iter.prev() to avoid O(n^2) behavior. */ | ||
54 | + | ||
55 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; | ||
56 | - skippy_iter.reset (buffer->idx, 1); | ||
57 | skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); | ||
58 | - do { | ||
59 | - unsigned unsafe_from; | ||
60 | - if (!skippy_iter.prev (&unsafe_from)) | ||
61 | + | ||
62 | + unsigned j; | ||
63 | + for (j = buffer->idx; j > c->last_base_until; j--) | ||
64 | + { | ||
65 | + auto match = skippy_iter.match (buffer->info[j - 1]); | ||
66 | + if (match == skippy_iter.MATCH) | ||
67 | { | ||
68 | - buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); | ||
69 | - return_trace (false); | ||
70 | + if (!accept (buffer, j - 1)) | ||
71 | + match = skippy_iter.SKIP; | ||
72 | } | ||
73 | + if (match == skippy_iter.MATCH) | ||
74 | + { | ||
75 | + c->last_base = (signed) j - 1; | ||
76 | + break; | ||
77 | + } | ||
78 | + } | ||
79 | + c->last_base_until = buffer->idx; | ||
80 | + if (c->last_base == -1) | ||
81 | + { | ||
82 | + buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1); | ||
83 | + return_trace (false); | ||
84 | + } | ||
85 | |||
86 | - /* We only want to attach to the first of a MultipleSubst sequence. | ||
87 | - * https://github.com/harfbuzz/harfbuzz/issues/740 | ||
88 | - * Reject others... | ||
89 | - * ...but stop if we find a mark in the MultipleSubst sequence: | ||
90 | - * https://github.com/harfbuzz/harfbuzz/issues/1020 */ | ||
91 | - if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) || | ||
92 | - 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) || | ||
93 | - (skippy_iter.idx == 0 || | ||
94 | - _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) || | ||
95 | - !_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx - 1]) || | ||
96 | - _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) != | ||
97 | - _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) || | ||
98 | - _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) != | ||
99 | - _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1 | ||
100 | - )) | ||
101 | - break; | ||
102 | - skippy_iter.reject (); | ||
103 | - } while (true); | ||
104 | + unsigned idx = (unsigned) c->last_base; | ||
105 | |||
106 | /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ | ||
107 | - //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); } | ||
108 | + //if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); } | ||
109 | |||
110 | - unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); | ||
111 | + unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint); | ||
112 | if (base_index == NOT_COVERED) | ||
113 | { | ||
114 | - buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1); | ||
115 | + buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1); | ||
116 | return_trace (false); | ||
117 | } | ||
118 | |||
119 | - return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); | ||
120 | + return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx)); | ||
121 | } | ||
122 | |||
123 | bool subset (hb_subset_context_t *c) const | ||
124 | diff --git a/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/src/OT/Layout/GPOS/MarkLigPosFormat1.hh | ||
125 | index 1a80212..4471871 100644 | ||
126 | --- a/src/OT/Layout/GPOS/MarkLigPosFormat1.hh | ||
127 | +++ b/src/OT/Layout/GPOS/MarkLigPosFormat1.hh | ||
128 | @@ -100,20 +100,32 @@ struct MarkLigPosFormat1_2 | ||
129 | if (likely (mark_index == NOT_COVERED)) return_trace (false); | ||
130 | |||
131 | /* Now we search backwards for a non-mark glyph */ | ||
132 | + | ||
133 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; | ||
134 | - skippy_iter.reset (buffer->idx, 1); | ||
135 | skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); | ||
136 | - unsigned unsafe_from; | ||
137 | - if (!skippy_iter.prev (&unsafe_from)) | ||
138 | + | ||
139 | + unsigned j; | ||
140 | + for (j = buffer->idx; j > c->last_base_until; j--) | ||
141 | { | ||
142 | - buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); | ||
143 | + auto match = skippy_iter.match (buffer->info[j - 1]); | ||
144 | + if (match == skippy_iter.MATCH) | ||
145 | + { | ||
146 | + c->last_base = (signed) j - 1; | ||
147 | + break; | ||
148 | + } | ||
149 | + } | ||
150 | + c->last_base_until = buffer->idx; | ||
151 | + if (c->last_base == -1) | ||
152 | + { | ||
153 | + buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1); | ||
154 | return_trace (false); | ||
155 | } | ||
156 | |||
157 | + j = (unsigned) c->last_base; | ||
158 | + | ||
159 | /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ | ||
160 | - //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); } | ||
161 | + //if (!_hb_glyph_info_is_ligature (&buffer->info[j])) { return_trace (false); } | ||
162 | |||
163 | - unsigned int j = skippy_iter.idx; | ||
164 | unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); | ||
165 | if (lig_index == NOT_COVERED) | ||
166 | { | ||
167 | diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh | ||
168 | index 04b823e..dc3c4b6 100644 | ||
169 | --- a/src/hb-ot-layout-gsubgpos.hh | ||
170 | +++ b/src/hb-ot-layout-gsubgpos.hh | ||
171 | @@ -701,6 +701,9 @@ struct hb_ot_apply_context_t : | ||
172 | uint32_t random_state = 1; | ||
173 | unsigned new_syllables = (unsigned) -1; | ||
174 | |||
175 | + signed last_base = -1; // GPOS uses | ||
176 | + unsigned last_base_until = 0; // GPOS uses | ||
177 | + | ||
178 | hb_ot_apply_context_t (unsigned int table_index_, | ||
179 | hb_font_t *font_, | ||
180 | hb_buffer_t *buffer_) : | ||
181 | @@ -738,7 +741,7 @@ struct hb_ot_apply_context_t : | ||
182 | iter_context.init (this, true); | ||
183 | } | ||
184 | |||
185 | - void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); } | ||
186 | + void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; last_base = -1; last_base_until = 0; init_iters (); } | ||
187 | void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); } | ||
188 | void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); } | ||
189 | void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; init_iters (); } | ||
190 | -- | ||
191 | 2.25.1 | ||
192 | |||
diff --git a/meta/recipes-graphics/harfbuzz/harfbuzz_5.1.0.bb b/meta/recipes-graphics/harfbuzz/harfbuzz_5.1.0.bb index 8e06acc011..0d68a4bf84 100644 --- a/meta/recipes-graphics/harfbuzz/harfbuzz_5.1.0.bb +++ b/meta/recipes-graphics/harfbuzz/harfbuzz_5.1.0.bb | |||
@@ -10,6 +10,8 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=6ee0f16281694fb6aa689cca1e0fb3da \ | |||
10 | 10 | ||
11 | SRC_URI = "${GITHUB_BASE_URI}/download/${PV}/${BPN}-${PV}.tar.xz \ | 11 | SRC_URI = "${GITHUB_BASE_URI}/download/${PV}/${BPN}-${PV}.tar.xz \ |
12 | file://0001-fix-signedness-of-char-in-tests.patch \ | 12 | file://0001-fix-signedness-of-char-in-tests.patch \ |
13 | file://CVE-2023-25193-pre1.patch \ | ||
14 | file://CVE-2023-25193.patch \ | ||
13 | " | 15 | " |
14 | SRC_URI[sha256sum] = "2edb95db668781aaa8d60959d21be2ff80085f31b12053cdd660d9a50ce84f05" | 16 | SRC_URI[sha256sum] = "2edb95db668781aaa8d60959d21be2ff80085f31b12053cdd660d9a50ce84f05" |
15 | 17 | ||