From 8f039ab4d624c545dd472e477c705c3f013f66c6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 15 Aug 2023 11:27:19 -0600 Subject: [PATCH] [COLR] Avoid infinite-loop through PaintColrLayers Fixes https://github.com/harfbuzz/harfbuzz/issues/4376 Fixes https://oss-fuzz.com/testcase-detail/5717524023738368 --- src/OT/Color/COLR/COLR.hh | 8 ++++++++ src/hb-ft-colr.hh | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/OT/Color/COLR/COLR.hh b/src/OT/Color/COLR/COLR.hh index 955166bb3..3618a02a9 100644 --- a/src/OT/Color/COLR/COLR.hh +++ b/src/OT/Color/COLR/COLR.hh @@ -70,6 +70,7 @@ public: hb_color_t foreground; VarStoreInstancer &instancer; hb_set_t current_glyphs; + hb_set_t current_layers; int depth_left = HB_MAX_NESTING_LEVEL; int edge_count = HB_COLRV1_MAX_EDGE_COUNT; @@ -2428,10 +2429,17 @@ void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList (); for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++) { + if (unlikely (c->current_layers.has (i))) + continue; + + c->current_layers.add (i); + const Paint &paint = paint_offset_lists.get_paint (i); c->funcs->push_group (c->data); c->recurse (paint); c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER); + + c->current_layers.del (i); } } diff --git a/src/hb-ft-colr.hh b/src/hb-ft-colr.hh index 7992c8805..26903164a 100644 --- a/src/hb-ft-colr.hh +++ b/src/hb-ft-colr.hh @@ -106,6 +106,7 @@ struct hb_ft_paint_context_t unsigned palette_index; hb_color_t foreground; hb_set_t current_glyphs; + hb_set_t current_layers; int depth_left = HB_MAX_NESTING_LEVEL; int edge_count = HB_COLRV1_MAX_EDGE_COUNT; }; @@ -221,9 +222,18 @@ _hb_ft_paint (hb_ft_paint_context_t *c, &paint.u.colr_layers.layer_iterator, &other_paint)) { + unsigned i = paint.u.colr_layers.layer_iterator.layer; + + if (unlikely (c->current_layers.has (i))) + continue; + + c->current_layers.add (i); + c->funcs->push_group (c->data); c->recurse (other_paint); c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER); + + c->current_layers.del (i); } } break;