harfbuzz: Security fix for CVE-2023-25193

Upstream-Status: Backport from [8708b9e081]
(From OE-Core rev: c22bbe9b45e38601b89138999dd157fad8513262)

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>
This commit is contained in:
Siddharth Doshi
2023-03-10 14:57:18 +05:30
committed by Richard Purdie
parent 3acc83f91a
commit 1982d0cc7c
4 changed files with 653 additions and 1 deletions

View File

@@ -0,0 +1,335 @@
From 3122c2cdc45a964efedad8953a2df67205c3e3a8 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad@behdad.org>
Date: Sat, 4 Dec 2021 19:50:33 -0800
Subject: [PATCH] [buffer] Add HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
Fixes https://github.com/harfbuzz/harfbuzz/issues/1463
Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/3122c2cdc45a964efedad8953a2df67205c3e3a8]
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.
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
---
src/hb-buffer.cc | 10 ++---
src/hb-buffer.h | 76 ++++++++++++++++++++++++++++++------
src/hb-buffer.hh | 33 ++++++++++------
src/hb-ot-layout-gsubgpos.hh | 39 +++++++++++++++---
src/hb-ot-shape.cc | 8 +---
5 files changed, 124 insertions(+), 42 deletions(-)
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 6131c86..bba5eae 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -610,14 +610,14 @@ done:
}
void
-hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end)
+hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end, hb_mask_t mask)
{
unsigned int cluster = (unsigned int) -1;
cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster);
- _unsafe_to_break_set_mask (info, start, end, cluster);
+ _unsafe_to_break_set_mask (info, start, end, cluster, mask);
}
void
-hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end)
+hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end, hb_mask_t mask)
{
if (!have_output)
{
@@ -631,8 +631,8 @@ hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int en
unsigned int cluster = (unsigned int) -1;
cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster);
cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster);
- _unsafe_to_break_set_mask (out_info, start, out_len, cluster);
- _unsafe_to_break_set_mask (info, idx, end, cluster);
+ _unsafe_to_break_set_mask (out_info, start, out_len, cluster, mask);
+ _unsafe_to_break_set_mask (info, idx, end, cluster, mask);
}
void
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index d5cb746..42dc92a 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -77,26 +77,76 @@ typedef struct hb_glyph_info_t
* @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the
* beginning of the cluster this glyph is part of,
* then both sides need to be re-shaped, as the
- * result might be different. On the flip side,
- * it means that when this flag is not present,
- * then it's safe to break the glyph-run at the
- * beginning of this cluster, and the two sides
- * represent the exact same result one would get
- * if breaking input text at the beginning of
- * this cluster and shaping the two sides
- * separately. This can be used to optimize
- * paragraph layout, by avoiding re-shaping
- * of each line after line-breaking, or limiting
- * the reshaping to a small piece around the
- * breaking point only.
+ * result might be different.
+ *
+ * On the flip side, it means that when this
+ * flag is not present, then it is safe to break
+ * the glyph-run at the beginning of this
+ * cluster, and the two sides will represent the
+ * exact same result one would get if breaking
+ * input text at the beginning of this cluster
+ * and shaping the two sides separately.
+ *
+ * This can be used to optimize paragraph
+ * layout, by avoiding re-shaping of each line
+ * after line-breaking.
+ *
+ * @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT: Indicates that if input text is changed on one
+ * side of the beginning of the cluster this glyph
+ * is part of, then the shaping results for the
+ * other side might change.
+ *
+ * Note that the absence of this flag will NOT by
+ * itself mean that it IS safe to concat text.
+ * Only two pieces of text both of which clear of
+ * this flag can be concatenated safely.
+ *
+ * This can be used to optimize paragraph
+ * layout, by avoiding re-shaping of each line
+ * after line-breaking, by limiting the
+ * reshaping to a small piece around the
+ * breaking positin only, even if the breaking
+ * position carries the
+ * #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when
+ * hyphenation or other text transformation
+ * happens at line-break position, in the following
+ * way:
+ *
+ * 1. Iterate back from the line-break position till
+ * the the first cluster start position that is
+ * NOT unsafe-to-concat, 2. shape the segment from
+ * there till the end of line, 3. check whether the
+ * resulting glyph-run also is clear of the
+ * unsafe-to-concat at its start-of-text position;
+ * if it is, just splice it into place and the line
+ * is shaped; If not, move on to a position further
+ * back that is clear of unsafe-to-concat and retry
+ * from there, and repeat.
+ *
+ * At the start of next line a similar algorithm can
+ * be implemented. A slight complication will arise,
+ * because while our buffer API has a way to
+ * return flags for position corresponding to
+ * start-of-text, there is currently no position
+ * corresponding to end-of-text. This limitation
+ * can be alleviated by shaping more text than needed
+ * and looking for unsafe-to-concat flag within text
+ * clusters.
+ *
+ * The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will
+ * always imply this flag.
+ *
+ * Since: REPLACEME
+ *
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
* Since: 1.5.0
*/
typedef enum { /*< flags >*/
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
+ HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
- HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */
+ HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */
} hb_glyph_flags_t;
HB_EXTERN hb_glyph_flags_t
diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh
index b5596d9..beac7b6 100644
--- a/src/hb-buffer.hh
+++ b/src/hb-buffer.hh
@@ -67,8 +67,8 @@ enum hb_buffer_scratch_flags_t {
HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
- HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u,
- HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000020u,
+ HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u,
+ HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u,
/* Reserved for complex shapers' internal use. */
HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
@@ -324,8 +324,19 @@ struct hb_buffer_t
return;
unsafe_to_break_impl (start, end);
}
- HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
- HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
+ void unsafe_to_concat (unsigned int start,
+ unsigned int end)
+ {
+ if (end - start < 2)
+ return;
+ unsafe_to_break_impl (start, end, HB_GLYPH_FLAG_UNSAFE_TO_CONCAT);
+ }
+ HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end,
+ hb_mask_t mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT);
+ HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end,
+ hb_mask_t mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT);
+ void unsafe_to_concat_from_outbuffer (unsigned int start, unsigned int end)
+ { unsafe_to_break_from_outbuffer (start, end, HB_GLYPH_FLAG_UNSAFE_TO_CONCAT); }
/* Internal methods */
@@ -377,12 +388,7 @@ struct hb_buffer_t
set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
{
if (inf.cluster != cluster)
- {
- if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
- inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
- else
- inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
- }
+ inf.mask = (inf.mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED);
inf.cluster = cluster;
}
@@ -398,13 +404,14 @@ struct hb_buffer_t
void
_unsafe_to_break_set_mask (hb_glyph_info_t *infos,
unsigned int start, unsigned int end,
- unsigned int cluster)
+ unsigned int cluster,
+ hb_mask_t mask)
{
for (unsigned int i = start; i < end; i++)
if (cluster != infos[i].cluster)
{
- scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
- infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+ scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
+ infos[i].mask |= mask;
}
}
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index 579d178..a6ca456 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -369,7 +369,7 @@ struct hb_ot_apply_context_t :
may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
- bool next ()
+ bool next (unsigned *unsafe_to = nullptr)
{
assert (num_items > 0);
while (idx + num_items < end)
@@ -392,11 +392,17 @@ struct hb_ot_apply_context_t :
}
if (skip == matcher_t::SKIP_NO)
+ {
+ if (unsafe_to)
+ *unsafe_to = idx + 1;
return false;
+ }
}
+ if (unsafe_to)
+ *unsafe_to = end;
return false;
}
- bool prev ()
+ bool prev (unsigned *unsafe_from = nullptr)
{
assert (num_items > 0);
while (idx > num_items - 1)
@@ -419,8 +425,14 @@ struct hb_ot_apply_context_t :
}
if (skip == matcher_t::SKIP_NO)
+ {
+ if (unsafe_from)
+ *unsafe_from = hb_max (1u, idx) - 1u;
return false;
+ }
}
+ if (unsafe_from)
+ *unsafe_from = 0;
return false;
}
@@ -834,7 +846,12 @@ static inline bool match_input (hb_ot_apply_context_t *c,
match_positions[0] = buffer->idx;
for (unsigned int i = 1; i < count; i++)
{
- if (!skippy_iter.next ()) return_trace (false);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
+ return_trace (false);
+ }
match_positions[i] = skippy_iter.idx;
@@ -1022,8 +1039,14 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
skippy_iter.set_match_func (match_func, match_data, backtrack);
for (unsigned int i = 0; i < count; i++)
- if (!skippy_iter.prev ())
+ {
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ c->buffer->unsafe_to_concat_from_outbuffer (unsafe_from, c->buffer->idx);
return_trace (false);
+ }
+ }
*match_start = skippy_iter.idx;
@@ -1045,8 +1068,14 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
skippy_iter.set_match_func (match_func, match_data, lookahead);
for (unsigned int i = 0; i < count; i++)
- if (!skippy_iter.next ())
+ {
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ c->buffer->unsafe_to_concat (c->buffer->idx + offset, unsafe_to);
return_trace (false);
+ }
+ }
*end_index = skippy_iter.idx + 1;
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 5d9a70c..5d10b30 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -1008,7 +1008,7 @@ hb_propagate_flags (hb_buffer_t *buffer)
/* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
* Simplifies using them. */
- if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK))
+ if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
return;
hb_glyph_info_t *info = buffer->info;
@@ -1017,11 +1017,7 @@ hb_propagate_flags (hb_buffer_t *buffer)
{
unsigned int mask = 0;
for (unsigned int i = start; i < end; i++)
- if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
- {
- mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
- break;
- }
+ mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
if (mask)
for (unsigned int i = start; i < end; i++)
info[i].mask |= mask;
--
2.25.1

View File

@@ -0,0 +1,135 @@
From b29fbd16fa82b82bdf0dcb2f13a63f7dc23cf324 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad@behdad.org>
Date: Mon, 6 Feb 2023 13:08:52 -0700
Subject: [PATCH] [gsubgpos] Refactor skippy_iter.match()
Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/b29fbd16fa82b82bdf0dcb2f13a63f7dc23cf324]
Comment1: To backport the fix for CVE-2023-25193, add defination for MATCH, NOT_MATCH and SKIP.
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
---
src/hb-ot-layout-gsubgpos.hh | 94 +++++++++++++++++++++---------------
1 file changed, 54 insertions(+), 40 deletions(-)
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index a6ca456..5a7e564 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -369,33 +369,52 @@ struct hb_ot_apply_context_t :
may_skip (const hb_glyph_info_t &info) const
{ return matcher.may_skip (c, info); }
+ enum match_t {
+ MATCH,
+ NOT_MATCH,
+ SKIP
+ };
+
+ match_t match (hb_glyph_info_t &info)
+ {
+ matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+ if (unlikely (skip == matcher_t::SKIP_YES))
+ return SKIP;
+
+ matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+ if (match == matcher_t::MATCH_YES ||
+ (match == matcher_t::MATCH_MAYBE &&
+ skip == matcher_t::SKIP_NO))
+ return MATCH;
+
+ if (skip == matcher_t::SKIP_NO)
+ return NOT_MATCH;
+
+ return SKIP;
+ }
+
bool next (unsigned *unsafe_to = nullptr)
{
assert (num_items > 0);
while (idx + num_items < end)
{
idx++;
- const hb_glyph_info_t &info = c->buffer->info[idx];
-
- matcher_t::may_skip_t skip = matcher.may_skip (c, info);
- if (unlikely (skip == matcher_t::SKIP_YES))
- continue;
-
- matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
- if (match == matcher_t::MATCH_YES ||
- (match == matcher_t::MATCH_MAYBE &&
- skip == matcher_t::SKIP_NO))
- {
- num_items--;
- if (match_glyph_data) match_glyph_data++;
- return true;
- }
-
- if (skip == matcher_t::SKIP_NO)
+ switch (match (c->buffer->info[idx]))
{
- if (unsafe_to)
- *unsafe_to = idx + 1;
- return false;
+ case MATCH:
+ {
+ num_items--;
+ if (match_glyph_data) match_glyph_data++;
+ return true;
+ }
+ case NOT_MATCH:
+ {
+ if (unsafe_to)
+ *unsafe_to = idx + 1;
+ return false;
+ }
+ case SKIP:
+ continue;
}
}
if (unsafe_to)
@@ -408,27 +427,22 @@ struct hb_ot_apply_context_t :
while (idx > num_items - 1)
{
idx--;
- const hb_glyph_info_t &info = c->buffer->out_info[idx];
-
- matcher_t::may_skip_t skip = matcher.may_skip (c, info);
- if (unlikely (skip == matcher_t::SKIP_YES))
- continue;
-
- matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
- if (match == matcher_t::MATCH_YES ||
- (match == matcher_t::MATCH_MAYBE &&
- skip == matcher_t::SKIP_NO))
+ switch (match (c->buffer->out_info[idx]))
{
- num_items--;
- if (match_glyph_data) match_glyph_data++;
- return true;
- }
-
- if (skip == matcher_t::SKIP_NO)
- {
- if (unsafe_from)
- *unsafe_from = hb_max (1u, idx) - 1u;
- return false;
+ case MATCH:
+ {
+ num_items--;
+ if (match_glyph_data) match_glyph_data++;
+ return true;
+ }
+ case NOT_MATCH:
+ {
+ if (unsafe_from)
+ *unsafe_from = hb_max (1u, idx) - 1u;
+ return false;
+ }
+ case SKIP:
+ continue;
}
}
if (unsafe_from)
--
2.25.1

View File

@@ -0,0 +1,179 @@
From 8708b9e081192786c027bb7f5f23d76dbe5c19e8 Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad@behdad.org>
Date: Mon, 6 Feb 2023 14:51:25 -0700
Subject: [PATCH] [GPOS] Avoid O(n^2) behavior in mark-attachment
Upstream-Status: Backport from [https://github.com/harfbuzz/harfbuzz/commit/8708b9e081192786c027bb7f5f23d76dbe5c19e8]
Comment1: The Original Patch [https://github.com/harfbuzz/harfbuzz/commit/85be877925ddbf34f74a1229f3ca1716bb6170dc] causes regression and was reverted. This Patch completes the fix.
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
CVE: CVE-2023-25193
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
---
src/hb-ot-layout-gpos-table.hh | 101 ++++++++++++++++++++++++---------
src/hb-ot-layout-gsubgpos.hh | 5 +-
2 files changed, 77 insertions(+), 29 deletions(-)
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 024312d..88df13d 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1458,6 +1458,25 @@ struct MarkBasePosFormat1
const Coverage &get_coverage () const { return this+markCoverage; }
+ static inline bool accept (hb_buffer_t *buffer, unsigned idx)
+ {
+ /* We only want to attach to the first of a MultipleSubst sequence.
+ * https://github.com/harfbuzz/harfbuzz/issues/740
+ * Reject others...
+ * ...but stop if we find a mark in the MultipleSubst sequence:
+ * https://github.com/harfbuzz/harfbuzz/issues/1020 */
+ return !_hb_glyph_info_multiplied (&buffer->info[idx]) ||
+ 0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) ||
+ (idx == 0 ||
+ _hb_glyph_info_is_mark (&buffer->info[idx - 1]) ||
+ !_hb_glyph_info_multiplied (&buffer->info[idx - 1]) ||
+ _hb_glyph_info_get_lig_id (&buffer->info[idx]) !=
+ _hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) ||
+ _hb_glyph_info_get_lig_comp (&buffer->info[idx]) !=
+ _hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1
+ );
+ }
+
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
@@ -1465,37 +1484,46 @@ struct MarkBasePosFormat1
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
if (likely (mark_index == NOT_COVERED)) return_trace (false);
- /* Now we search backwards for a non-mark glyph */
+ /* Now we search backwards for a non-mark glyph.
+ * We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
+
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
- do {
- if (!skippy_iter.prev ()) return_trace (false);
- /* We only want to attach to the first of a MultipleSubst sequence.
- * https://github.com/harfbuzz/harfbuzz/issues/740
- * Reject others...
- * ...but stop if we find a mark in the MultipleSubst sequence:
- * https://github.com/harfbuzz/harfbuzz/issues/1020 */
- if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
- 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
- (skippy_iter.idx == 0 ||
- _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
- _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
- _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
- _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
- _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
- ))
- break;
- skippy_iter.reject ();
- } while (true);
+ unsigned j;
+ for (j = buffer->idx; j > c->last_base_until; j--)
+ {
+ auto match = skippy_iter.match (buffer->info[j - 1]);
+ if (match == skippy_iter.MATCH)
+ {
+ if (!accept (buffer, j - 1))
+ match = skippy_iter.SKIP;
+ }
+ if (match == skippy_iter.MATCH)
+ {
+ c->last_base = (signed) j - 1;
+ break;
+ }
+ }
+ c->last_base_until = buffer->idx;
+ if (c->last_base == -1)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ unsigned idx = (unsigned) c->last_base;
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
- //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
+ //if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); }
- unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
+ unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint);
if (base_index == NOT_COVERED) return_trace (false);
+ {
+ buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
+ return_trace (false);
+ }
- return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
+ return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx));
}
bool subset (hb_subset_context_t *c) const
@@ -1587,15 +1615,32 @@ struct MarkLigPosFormat1
if (likely (mark_index == NOT_COVERED)) return_trace (false);
/* Now we search backwards for a non-mark glyph */
+
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
- if (!skippy_iter.prev ()) return_trace (false);
+
+ unsigned j;
+ for (j = buffer->idx; j > c->last_base_until; j--)
+ {
+ auto match = skippy_iter.match (buffer->info[j - 1]);
+ if (match == skippy_iter.MATCH)
+ {
+ c->last_base = (signed) j - 1;
+ break;
+ }
+ }
+ c->last_base_until = buffer->idx;
+ if (c->last_base == -1)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ j = (unsigned) c->last_base;
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
- //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
+ //if (!_hb_glyph_info_is_ligature (&buffer->info[idx])) { return_trace (false); }
- unsigned int j = skippy_iter.idx;
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
if (lig_index == NOT_COVERED) return_trace (false);
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index 5a7e564..437123c 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -503,6 +503,9 @@ struct hb_ot_apply_context_t :
uint32_t random_state;
+ signed last_base = -1; // GPOS uses
+ unsigned last_base_until = 0; // GPOS uses
+
hb_ot_apply_context_t (unsigned int table_index_,
hb_font_t *font_,
hb_buffer_t *buffer_) :
@@ -536,7 +539,7 @@ struct hb_ot_apply_context_t :
iter_context.init (this, true);
}
- void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
+ void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; last_base = -1; last_base_until = 0; init_iters (); }
void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
void set_random (bool random_) { random = random_; }
--
2.25.1

View File

@@ -7,7 +7,10 @@ LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://COPYING;md5=e11f5c3149cdec4bb309babb020b32b9 \
file://src/hb-ucd.cc;beginline=1;endline=15;md5=29d4dcb6410429195df67efe3382d8bc"
SRC_URI = "http://www.freedesktop.org/software/harfbuzz/release/${BP}.tar.xz"
SRC_URI = "http://www.freedesktop.org/software/harfbuzz/release/${BP}.tar.xz \
file://CVE-2023-25193-pre0.patch \
file://CVE-2023-25193-pre1.patch \
file://CVE-2023-25193.patch"
SRC_URI[md5sum] = "2b3a4dfdb3e5e50055f941978944da9f"
SRC_URI[sha256sum] = "9413b8d96132d699687ef914ebb8c50440efc87b3f775d25856d7ec347c03c12"