From 85646fdadb2f102333485e07425361795b4e0412 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Mon, 23 Jul 2018 15:37:18 -0700 Subject: [PATCH] [subset] Limit the iterations of the closure algorithm. Prevents O(n^2) run times. --- src/hb-ot-layout-common-private.hh | 7 +++++++ src/hb-ot-layout.cc | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 21caf9e95..7ff0dbebb 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -41,6 +41,13 @@ #ifndef HB_MAX_CONTEXT_LENGTH #define HB_MAX_CONTEXT_LENGTH 64 #endif +#ifndef HB_CLOSURE_MAX_STAGES +/* + * The maximum number of times a lookup can be applied during shaping. + * Used to limit the number of iterations of the closure algorithm. + */ +#define HB_CLOSURE_MAX_STAGES 8 +#endif namespace OT { diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 0eba88a62..01ca5143d 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -971,6 +971,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, OT::hb_closure_context_t c (face, glyphs, &done_lookups); const OT::GSUB& gsub = _get_gsub (face); + unsigned int iteration_count = 0; unsigned int glyphs_length; do { @@ -985,7 +986,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, for (unsigned int i = 0; i < gsub.get_lookup_count (); i++) gsub.get_lookup (i).closure (&c, i); } - } while (glyphs_length != glyphs->get_population ()); + iteration_count++; + } while (iteration_count <= HB_CLOSURE_MAX_STAGES + && glyphs_length != glyphs->get_population ()); } /*