summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSiddharth <sdoshi@mvista.com>2023-03-11 16:54:13 +0530
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-03-21 14:26:31 +0000
commite0b2ca58679f610d01fb8a99e656e4b812c69418 (patch)
tree33e7bb7784c514c548316905a09f21d6cf579dff
parent830eb878166d531d9188176ae40a25c54a309e6c (diff)
downloadpoky-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>
-rw-r--r--meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193-pre1.patch135
-rw-r--r--meta/recipes-graphics/harfbuzz/harfbuzz/CVE-2023-25193.patch192
-rw-r--r--meta/recipes-graphics/harfbuzz/harfbuzz_5.1.0.bb2
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 @@
1From b29fbd16fa82b82bdf0dcb2f13a63f7dc23cf324 Mon Sep 17 00:00:00 2001
2From: Behdad Esfahbod <behdad@behdad.org>
3Date: Mon, 6 Feb 2023 13:08:52 -0700
4Subject: [PATCH] [gsubgpos] Refactor skippy_iter.match()
5
6Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/b29fbd16fa82b82bdf0dcb2f13a63f7dc23cf324]
7Comment1: To backport the fix for CVE-2023-25193, add defination for MATCH, NOT_MATCH and SKIP.
8Signed-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
13diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
14index 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--
1342.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 @@
1From 8708b9e081192786c027bb7f5f23d76dbe5c19e8 Mon Sep 17 00:00:00 2001
2From: Behdad Esfahbod <behdad@behdad.org>
3Date: Mon, 6 Feb 2023 14:51:25 -0700
4Subject: [PATCH] [GPOS] Avoid O(n^2) behavior in mark-attachment
5
6Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/8708b9e081192786c027bb7f5f23d76dbe5c19e8]
7Comment1: The Original Patch [https://github.com/harfbuzz/harfbuzz/commit/85be877925ddbf34f74a1229f3ca1716bb6170dc] causes regression and was reverted. This Patch completes the fix.
8CVE: CVE-2023-25193
9Signed-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
17diff --git a/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
18index 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
124diff --git a/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
125index 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 {
167diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
168index 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--
1912.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
11SRC_URI = "${GITHUB_BASE_URI}/download/${PV}/${BPN}-${PV}.tar.xz \ 11SRC_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 "
14SRC_URI[sha256sum] = "2edb95db668781aaa8d60959d21be2ff80085f31b12053cdd660d9a50ce84f05" 16SRC_URI[sha256sum] = "2edb95db668781aaa8d60959d21be2ff80085f31b12053cdd660d9a50ce84f05"
15 17