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 | ||
