diff options
author | Siddharth Doshi <sdoshi@mvista.com> | 2023-03-10 14:00:36 +0530 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-03-20 17:20:44 +0000 |
commit | b7da7c8996257d3b249688744fb394f49168749c (patch) | |
tree | 08d37a432657709b552860e62fdbdb18363bbae6 /meta/recipes-graphics | |
parent | 347ea091f51a173895dee864b2f143eebb2c2b43 (diff) | |
download | poky-b7da7c8996257d3b249688744fb394f49168749c.tar.gz |
harfbuzz: Security fix for CVE-2023-25193
Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/8708b9e081192786c027bb7f5f23d76dbe5c19e8]
(From OE-Core rev: 58e212a6109a639ca0675e73967da74d6c4c5aa3)
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>
Diffstat (limited to 'meta/recipes-graphics')
3 files changed, 323 insertions, 1 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..6721b1bd70 --- /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 <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 d9a068c..d17a4da 100644 | ||
15 | --- a/src/hb-ot-layout-gsubgpos.hh | ||
16 | +++ b/src/hb-ot-layout-gsubgpos.hh | ||
17 | @@ -522,33 +522,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 | @@ -561,27 +580,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 | - { | ||
105 | - num_items--; | ||
106 | - if (match_glyph_data) match_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 | + 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..a1ec1422cc --- /dev/null +++ b/meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193.patch | |||
@@ -0,0 +1,185 @@ | |||
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 | 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 | --- | ||
12 | src/hb-ot-layout-gpos-table.hh | 98 ++++++++++++++++++++++------------ | ||
13 | src/hb-ot-layout-gsubgpos.hh | 5 +- | ||
14 | 2 files changed, 68 insertions(+), 35 deletions(-) | ||
15 | |||
16 | diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh | ||
17 | index 2f9186a..46b09d0 100644 | ||
18 | --- a/src/hb-ot-layout-gpos-table.hh | ||
19 | +++ b/src/hb-ot-layout-gpos-table.hh | ||
20 | @@ -2150,6 +2150,25 @@ struct MarkBasePosFormat1 | ||
21 | |||
22 | const Coverage &get_coverage () const { return this+markCoverage; } | ||
23 | |||
24 | + static inline bool accept (hb_buffer_t *buffer, unsigned idx) | ||
25 | + { | ||
26 | + /* We only want to attach to the first of a MultipleSubst sequence. | ||
27 | + * https://github.com/harfbuzz/harfbuzz/issues/740 | ||
28 | + * Reject others... | ||
29 | + * ...but stop if we find a mark in the MultipleSubst sequence: | ||
30 | + * https://github.com/harfbuzz/harfbuzz/issues/1020 */ | ||
31 | + return !_hb_glyph_info_multiplied (&buffer->info[idx]) || | ||
32 | + 0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) || | ||
33 | + (idx == 0 || | ||
34 | + _hb_glyph_info_is_mark (&buffer->info[idx - 1]) || | ||
35 | + !_hb_glyph_info_multiplied (&buffer->info[idx - 1]) || | ||
36 | + _hb_glyph_info_get_lig_id (&buffer->info[idx]) != | ||
37 | + _hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) || | ||
38 | + _hb_glyph_info_get_lig_comp (&buffer->info[idx]) != | ||
39 | + _hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1 | ||
40 | + ); | ||
41 | + } | ||
42 | + | ||
43 | bool apply (hb_ot_apply_context_t *c) const | ||
44 | { | ||
45 | TRACE_APPLY (this); | ||
46 | @@ -2157,47 +2176,46 @@ struct MarkBasePosFormat1 | ||
47 | unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); | ||
48 | if (likely (mark_index == NOT_COVERED)) return_trace (false); | ||
49 | |||
50 | - /* Now we search backwards for a non-mark glyph */ | ||
51 | + /* Now we search backwards for a non-mark glyph. | ||
52 | + * We don't use skippy_iter.prev() to avoid O(n^2) behavior. */ | ||
53 | + | ||
54 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; | ||
55 | - skippy_iter.reset (buffer->idx, 1); | ||
56 | skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); | ||
57 | - do { | ||
58 | - unsigned unsafe_from; | ||
59 | - if (!skippy_iter.prev (&unsafe_from)) | ||
60 | + unsigned j; | ||
61 | + for (j = buffer->idx; j > c->last_base_until; j--) | ||
62 | + { | ||
63 | + auto match = skippy_iter.match (buffer->info[j - 1]); | ||
64 | + if (match == skippy_iter.MATCH) | ||
65 | { | ||
66 | - buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); | ||
67 | - return_trace (false); | ||
68 | + if (!accept (buffer, j - 1)) | ||
69 | + match = skippy_iter.SKIP; | ||
70 | } | ||
71 | + if (match == skippy_iter.MATCH) | ||
72 | + { | ||
73 | + c->last_base = (signed) j - 1; | ||
74 | + break; | ||
75 | + } | ||
76 | + } | ||
77 | + c->last_base_until = buffer->idx; | ||
78 | + if (c->last_base == -1) | ||
79 | + { | ||
80 | + buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1); | ||
81 | + return_trace (false); | ||
82 | + } | ||
83 | |||
84 | - /* We only want to attach to the first of a MultipleSubst sequence. | ||
85 | - * https://github.com/harfbuzz/harfbuzz/issues/740 | ||
86 | - * Reject others... | ||
87 | - * ...but stop if we find a mark in the MultipleSubst sequence: | ||
88 | - * https://github.com/harfbuzz/harfbuzz/issues/1020 */ | ||
89 | - if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) || | ||
90 | - 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) || | ||
91 | - (skippy_iter.idx == 0 || | ||
92 | - _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) || | ||
93 | - _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) != | ||
94 | - _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) || | ||
95 | - _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) != | ||
96 | - _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1 | ||
97 | - )) | ||
98 | - break; | ||
99 | - skippy_iter.reject (); | ||
100 | - } while (true); | ||
101 | + unsigned idx = (unsigned) c->last_base; | ||
102 | |||
103 | /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ | ||
104 | - //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); } | ||
105 | + //if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); } | ||
106 | |||
107 | - unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); | ||
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 (skippy_iter.idx, buffer->idx + 1); | ||
112 | + buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1); | ||
113 | return_trace (false); | ||
114 | } | ||
115 | |||
116 | - return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); | ||
117 | + return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx)); | ||
118 | } | ||
119 | |||
120 | bool subset (hb_subset_context_t *c) const | ||
121 | @@ -2423,20 +2441,32 @@ struct MarkLigPosFormat1 | ||
122 | if (likely (mark_index == NOT_COVERED)) return_trace (false); | ||
123 | |||
124 | /* Now we search backwards for a non-mark glyph */ | ||
125 | + | ||
126 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; | ||
127 | - skippy_iter.reset (buffer->idx, 1); | ||
128 | skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); | ||
129 | - unsigned unsafe_from; | ||
130 | - if (!skippy_iter.prev (&unsafe_from)) | ||
131 | + | ||
132 | + unsigned j; | ||
133 | + for (j = buffer->idx; j > c->last_base_until; j--) | ||
134 | { | ||
135 | - buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1); | ||
136 | + auto match = skippy_iter.match (buffer->info[j - 1]); | ||
137 | + if (match == skippy_iter.MATCH) | ||
138 | + { | ||
139 | + c->last_base = (signed) j - 1; | ||
140 | + break; | ||
141 | + } | ||
142 | + } | ||
143 | + c->last_base_until = buffer->idx; | ||
144 | + if (c->last_base == -1) | ||
145 | + { | ||
146 | + buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1); | ||
147 | return_trace (false); | ||
148 | } | ||
149 | |||
150 | + j = (unsigned) c->last_base; | ||
151 | + | ||
152 | /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ | ||
153 | - //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); } | ||
154 | + //if (!_hb_glyph_info_is_ligature (&buffer->info[j])) { return_trace (false); } | ||
155 | |||
156 | - unsigned int j = skippy_iter.idx; | ||
157 | unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); | ||
158 | if (lig_index == NOT_COVERED) | ||
159 | { | ||
160 | diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh | ||
161 | index 65de131..d9a068c 100644 | ||
162 | --- a/src/hb-ot-layout-gsubgpos.hh | ||
163 | +++ b/src/hb-ot-layout-gsubgpos.hh | ||
164 | @@ -641,6 +641,9 @@ struct hb_ot_apply_context_t : | ||
165 | uint32_t random_state; | ||
166 | |||
167 | |||
168 | + signed last_base = -1; // GPOS uses | ||
169 | + unsigned last_base_until = 0; // GPOS uses | ||
170 | + | ||
171 | hb_ot_apply_context_t (unsigned int table_index_, | ||
172 | hb_font_t *font_, | ||
173 | hb_buffer_t *buffer_) : | ||
174 | @@ -673,7 +676,7 @@ struct hb_ot_apply_context_t : | ||
175 | iter_context.init (this, true); | ||
176 | } | ||
177 | |||
178 | - void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); } | ||
179 | + void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; last_base = -1; last_base_until = 0; init_iters (); } | ||
180 | void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); } | ||
181 | void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); } | ||
182 | void set_random (bool random_) { random = random_; } | ||
183 | -- | ||
184 | 2.25.1 | ||
185 | |||
diff --git a/meta/recipes-graphics/harfbuzz/harfbuzz_4.0.1.bb b/meta/recipes-graphics/harfbuzz/harfbuzz_4.0.1.bb index bdbb322e42..f7dc61ebd5 100644 --- a/meta/recipes-graphics/harfbuzz/harfbuzz_4.0.1.bb +++ b/meta/recipes-graphics/harfbuzz/harfbuzz_4.0.1.bb | |||
@@ -13,7 +13,9 @@ UPSTREAM_CHECK_REGEX = "harfbuzz-(?P<pver>\d+(\.\d+)+).tar" | |||
13 | 13 | ||
14 | SRC_URI = "https://github.com/${BPN}/${BPN}/releases/download/${PV}/${BPN}-${PV}.tar.xz \ | 14 | SRC_URI = "https://github.com/${BPN}/${BPN}/releases/download/${PV}/${BPN}-${PV}.tar.xz \ |
15 | file://CVE-2022-33068.patch \ | 15 | file://CVE-2022-33068.patch \ |
16 | file://0001-Fix-conditional.patch" | 16 | file://0001-Fix-conditional.patch \ |
17 | file://CVE-2023-25193-pre1.patch \ | ||
18 | file://CVE-2023-25193.patch" | ||
17 | SRC_URI[sha256sum] = "98f68777272db6cd7a3d5152bac75083cd52a26176d87bc04c8b3929d33bce49" | 19 | SRC_URI[sha256sum] = "98f68777272db6cd7a3d5152bac75083cd52a26176d87bc04c8b3929d33bce49" |
18 | 20 | ||
19 | inherit meson pkgconfig lib_package gtk-doc gobject-introspection | 21 | inherit meson pkgconfig lib_package gtk-doc gobject-introspection |