Commit 232243e7495d142f30d4e024f30eda9ca8655154

Werner Lemberg 2021-06-19T06:32:29

Prevent hinting if there are too many segments. This speeds up handling of broken glyphs. Reported as https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35309 * src/autofit/aflatin.c (af_latin_hints_compute_segments): Implement it.

diff --git a/ChangeLog b/ChangeLog
index 7bd450a..522d084 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2021-06-19  Werner Lemberg  <david@freetype.org>
+
+	[autofit] Prevent hinting if there are too many segments.
+
+	This speeds up handling of broken glyphs.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35309
+
+	* src/autofit/aflatin.c (af_latin_hints_compute_segments): Implement
+	it.
+
 2021-06-18  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	* src/sdf/ftsdfrend.c (ft_(b)sdf_render): Do not FT_ERROR routinely.
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index ef90c93..8ca6ac2 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -1847,6 +1847,31 @@
              ( FT_ABS( point->out_dir ) == major_dir ||
                point == point->prev                  ) )
         {
+          /*
+           * For efficiency, we restrict the number of segments to 1000,
+           * which is a heuristic value: it is very unlikely that a glyph
+           * with so many segments can be hinted in a sensible way.
+           * Reasons:
+           *
+           * - The glyph has really 1000 segments; this implies that it has
+           *   at least 2000 outline points.  Assuming 'normal' fonts that
+           *   have superfluous points optimized away, viewing such a glyph
+           *   only makes sense at large magnifications where hinting
+           *   isn't applied anyway.
+           *
+           * - We have a broken glyph.  Hinting doesn't make sense in this
+           *   case either.
+           */
+          if ( axis->num_segments > 1000 )
+          {
+            FT_TRACE0(( "af_latin_hints_compute_segments:"
+                        " more than 1000 segments in this glyph;\n" ));
+            FT_TRACE0(( "                                "
+                        " hinting is suppressed\n" ));
+            axis->num_segments = 0;
+            return FT_Err_Ok;
+          }
+
           /* this is the start of a new segment! */
           segment_dir = (AF_Direction)point->out_dir;