[HarfBuzz] harfbuzz: Branch 'master' - 27 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Mar 21 01:49:03 UTC 2018


 CMakeLists.txt                                                |   23 --
 appveyor.yml                                                  |    7 
 configure.ac                                                  |    2 
 m4/ax_check_link_flag.m4                                      |   74 ++++++++
 src/Makefile.am                                               |   15 +
 src/gen-def.py                                                |    2 
 src/hb-directwrite.cc                                         |   19 --
 src/hb-ot-glyf-table.hh                                       |    9 -
 src/hb-ot-hdmx-table.hh                                       |   30 ++-
 src/hb-ot-hmtx-table.hh                                       |   13 +
 src/hb-subset-glyf.cc                                         |    9 -
 src/hb-subset.cc                                              |    1 
 test/api/Makefile.am                                          |    1 
 test/api/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249 |binary
 test/api/fonts/crash-b577db318b30f2851828a4c9ef97cb30678b1b54 |binary
 test/api/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a |binary
 test/api/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480 |binary
 test/api/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653   |binary
 test/api/test-subset-hdmx.c                                   |   23 ++
 test/api/test-subset-hmtx.c                                   |   23 ++
 test/api/test-subset.c                                        |   85 ++++++++++
 test/fuzzing/CMakeLists.txt                                   |   25 ++
 test/fuzzing/Makefile.am                                      |   35 +++-
 test/fuzzing/hb-subset-fuzzer.cc                              |   39 ++++
 test/fuzzing/run-fuzzer-tests.py                              |   32 ---
 test/fuzzing/run-shape-fuzzer-tests.py                        |   34 ++++
 test/fuzzing/run-subset-fuzzer-tests.py                       |   35 ++++
 27 files changed, 441 insertions(+), 95 deletions(-)

New commits:
commit 3f55e0e74680c246819233a7250df612821698d7
Author: Garret Rieger <grieger at google.com>
Date:   Tue Mar 20 17:36:52 2018 -0700

    [subset] Check for the Null table and not nullptr to detect failure to find a table in glyf accelerator.

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 11c3eaac..79467061 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -236,9 +236,9 @@ struct glyf
 
       hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
       const head *head_table = Sanitizer<head>::lock_instance (head_blob);
-      if (!head_table || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
+      if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
       {
-	/* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
+	/* head table is not present, or in an unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
 	hb_blob_destroy (head_blob);
 	return;
       }
@@ -268,7 +268,7 @@ struct glyf
     inline bool get_composite (hb_codepoint_t glyph,
 			       CompositeGlyphHeader::Iterator *composite /* OUT */) const
     {
-      if (!this->glyf_table || !num_glyphs)
+      if (this->glyf_table == &Null(glyf) || !num_glyphs)
 	return false;
 
       unsigned int start_offset, end_offset;
commit 45def99eae81e470be3c38d2962aafaaa85500b9
Author: Garret Rieger <grieger at google.com>
Date:   Tue Mar 20 17:28:47 2018 -0700

    [subset] Fix to debug message.

diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index 4d111008..1bbcbdcd 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -45,7 +45,7 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
     hb_codepoint_t next_glyph = glyph_ids[i];
     if (!instruction_ranges->resize (instruction_ranges->len + 2))
     {
-      DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.", next_glyph);
+      DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
       return false;
     }
     unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->len - 2];
commit 139661404006b8be039436a81cb6b1a73ec44042
Author: Garret Rieger <grieger at google.com>
Date:   Tue Mar 20 16:55:42 2018 -0700

    [subset] don't use pointers returned from push after array has resized in hb-subset-glyf.cc

diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index 0b84c856..4d111008 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -43,9 +43,14 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
   for (unsigned int i = 0; i < glyph_ids.len; i++)
   {
     hb_codepoint_t next_glyph = glyph_ids[i];
-    unsigned int *instruction_start = instruction_ranges->push();
-    unsigned int *instruction_end = instruction_ranges->push();
+    if (!instruction_ranges->resize (instruction_ranges->len + 2))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.", next_glyph);
+      return false;
+    }
+    unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->len - 2];
     *instruction_start = 0;
+    unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->len - 1];
     *instruction_end = 0;
 
     unsigned int start_offset, end_offset;
diff --git a/test/api/fonts/crash-b577db318b30f2851828a4c9ef97cb30678b1b54 b/test/api/fonts/crash-b577db318b30f2851828a4c9ef97cb30678b1b54
new file mode 100644
index 00000000..00be056e
Binary files /dev/null and b/test/api/fonts/crash-b577db318b30f2851828a4c9ef97cb30678b1b54 differ
commit 3531efdb4c641ef543ea0686fef9289307d52096
Author: Garret Rieger <grieger at google.com>
Date:   Tue Mar 20 16:31:21 2018 -0700

    [subset] Fixed out of bounds read when subsetting hdmx.

diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh
index f08fe39d..8df99576 100644
--- a/src/hb-ot-hdmx-table.hh
+++ b/src/hb-ot-hdmx-table.hh
@@ -43,12 +43,15 @@ struct DeviceRecord
   struct SubsetView
   {
     const DeviceRecord *source_device_record;
+    unsigned int size_device_record;
     hb_subset_plan_t *subset_plan;
 
     inline void init(const DeviceRecord *source_device_record,
+		     unsigned int size_device_record,
 		     hb_subset_plan_t   *subset_plan)
     {
       this->source_device_record = source_device_record;
+      this->size_device_record = size_device_record;
       this->subset_plan = subset_plan;
     }
 
@@ -57,11 +60,17 @@ struct DeviceRecord
       return this->subset_plan->gids_to_retain_sorted.len;
     }
 
-    inline const HBUINT8& operator [] (unsigned int i) const
+    inline const HBUINT8* operator [] (unsigned int i) const
     {
-      if (unlikely (i >= len())) return Null(HBUINT8);
+      if (unlikely (i >= len())) return nullptr;
       hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i];
-      return this->source_device_record->widths[gid];
+
+      const HBUINT8* width = &(this->source_device_record->widths[gid]);
+
+      if (width < ((const HBUINT8 *) this->source_device_record) + size_device_record)
+	return width;
+      else
+	return nullptr;
     }
   };
 
@@ -85,7 +94,15 @@ struct DeviceRecord
     this->max_width.set (subset_view.source_device_record->max_width);
 
     for (unsigned int i = 0; i < subset_view.len(); i++)
-      widths[i].set (subset_view[i]);
+    {
+      const HBUINT8 *width = subset_view[i];
+      if (!width)
+      {
+	DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
+	return_trace (false);
+      }
+      widths[i].set (*width);
+    }
 
     return_trace (true);
   }
@@ -133,9 +150,10 @@ struct hdmx
     for (unsigned int i = 0; i < source_hdmx->num_records; i++)
     {
       DeviceRecord::SubsetView subset_view;
-      subset_view.init (&(*source_hdmx)[i], plan);
+      subset_view.init (&(*source_hdmx)[i], source_hdmx->size_device_record, plan);
 
-      c->start_embed<DeviceRecord> ()->serialize (c, subset_view);
+      if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
+	return_trace (false);
     }
 
     return_trace (true);
diff --git a/test/api/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a b/test/api/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a
new file mode 100644
index 00000000..1af243eb
Binary files /dev/null and b/test/api/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a differ
diff --git a/test/api/test-subset-hdmx.c b/test/api/test-subset-hdmx.c
index 609ee061..dd20b2a2 100644
--- a/test/api/test-subset-hdmx.c
+++ b/test/api/test-subset-hdmx.c
@@ -51,6 +51,28 @@ test_subset_hdmx_simple_subset (void)
 }
 
 static void
+test_subset_hdmx_invalid (void)
+{
+  hb_face_t *face = hb_subset_test_open_font("fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
+
+  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
+  hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+
+  hb_subset_profile_t *profile = hb_subset_profile_create();
+  hb_face_t *subset = hb_subset (face, profile, input);
+  g_assert (subset);
+  g_assert (subset == hb_face_get_empty ());
+
+  hb_subset_input_destroy (input);
+  hb_subset_profile_destroy (profile);
+  hb_face_destroy (subset);
+  hb_face_destroy (face);
+}
+
+static void
 test_subset_hdmx_noop (void)
 {
   hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf");
@@ -75,6 +97,7 @@ main (int argc, char **argv)
   hb_test_init (&argc, &argv);
 
   hb_test_add (test_subset_hdmx_simple_subset);
+  hb_test_add (test_subset_hdmx_invalid);
   hb_test_add (test_subset_hdmx_noop);
 
   return hb_test_run();
commit e597436b994c0a553e85e4c2dbd74aa037e69b60
Author: Garret Rieger <grieger at google.com>
Date:   Tue Mar 20 13:00:49 2018 -0700

    [subset] Disable glyf accelerator_t methods if it didn't successfully init.

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index d62f24bd..11c3eaac 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -232,9 +232,11 @@ struct glyf
   {
     inline void init (hb_face_t *face)
     {
+      memset (this, 0, sizeof (accelerator_t));
+
       hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
       const head *head_table = Sanitizer<head>::lock_instance (head_blob);
-      if ((unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
+      if (!head_table || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
       {
 	/* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
 	hb_blob_destroy (head_blob);
@@ -266,6 +268,9 @@ struct glyf
     inline bool get_composite (hb_codepoint_t glyph,
 			       CompositeGlyphHeader::Iterator *composite /* OUT */) const
     {
+      if (!this->glyf_table || !num_glyphs)
+	return false;
+
       unsigned int start_offset, end_offset;
       if (!get_offsets (glyph, &start_offset, &end_offset))
         return false; /* glyph not found */
diff --git a/test/api/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249 b/test/api/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249
new file mode 100644
index 00000000..b6b47ffe
Binary files /dev/null and b/test/api/fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249 differ
diff --git a/test/api/test-subset.c b/test/api/test-subset.c
index 6f71e04d..6bf5c066 100644
--- a/test/api/test-subset.c
+++ b/test/api/test-subset.c
@@ -51,12 +51,35 @@ test_subset_32_tables (void)
   hb_face_destroy (face);
 }
 
+static void
+test_subset_crash (void)
+{
+  hb_face_t *face = hb_subset_test_open_font("fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249");
+
+  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
+  hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+
+  hb_subset_profile_t *profile = hb_subset_profile_create();
+  hb_face_t *subset = hb_subset (face, profile, input);
+  g_assert (subset);
+  g_assert (subset == hb_face_get_empty ());
+
+  hb_subset_input_destroy (input);
+  hb_subset_profile_destroy (profile);
+  hb_face_destroy (subset);
+  hb_face_destroy (face);
+}
+
 int
 main (int argc, char **argv)
 {
   hb_test_init (&argc, &argv);
 
   hb_test_add (test_subset_32_tables);
+  hb_test_add (test_subset_crash);
 
   return hb_test_run();
 }
commit 7251181b56af564e2a9444f002f8ac03f98c7ee3
Author: Garret Rieger <grieger at google.com>
Date:   Tue Mar 20 11:21:06 2018 -0700

    [subset] Fix infinite loop in there are more then 32 tables.

diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 30cba3fc..75121c56 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -359,6 +359,7 @@ hb_subset (hb_face_t *source,
         continue;
       }
       success = success && _subset_table (plan, tag);
+      offset += count;
     }
   } while (count == ARRAY_LENGTH (table_tags));
 
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index 54e367fa..0e63b1d7 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -31,6 +31,7 @@ TEST_PROGS = \
 	test-object \
 	test-set \
 	test-shape \
+	test-subset \
 	test-subset-cmap \
 	test-subset-glyf \
 	test-subset-hdmx \
diff --git a/test/api/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653 b/test/api/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653
new file mode 100644
index 00000000..0bb0f0f0
Binary files /dev/null and b/test/api/fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653 differ
diff --git a/test/api/test-subset.c b/test/api/test-subset.c
new file mode 100644
index 00000000..6f71e04d
--- /dev/null
+++ b/test/api/test-subset.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+/* Unit tests for hb-subset-glyf.h */
+
+static void
+test_subset_32_tables (void)
+{
+  hb_face_t *face = hb_subset_test_open_font("fonts/oom-6ef8c96d3710262511bcc730dce9c00e722cb653");
+
+  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
+  hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+
+  hb_subset_profile_t *profile = hb_subset_profile_create();
+  hb_face_t *subset = hb_subset (face, profile, input);
+  g_assert (subset);
+  g_assert (subset != hb_face_get_empty ());
+
+  hb_subset_input_destroy (input);
+  hb_subset_profile_destroy (profile);
+  hb_face_destroy (subset);
+  hb_face_destroy (face);
+}
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_subset_32_tables);
+
+  return hb_test_run();
+}
commit 1a94804d35d533d39849d21a177039c4cbfade98
Author: Garret Rieger <grieger at google.com>
Date:   Mon Mar 19 18:39:22 2018 -0700

    [subset] Add a fix for segfault in hmtx/vmtx subsetting code.

diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index bff792a6..2af9a5cc 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -118,6 +118,8 @@ struct hmtxvmtx
     LongMetric * old_metrics = (LongMetric *) source_table;
     FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
     char * dest_pos = (char *) dest;
+
+    bool failed = false;
     for (unsigned int i = 0; i < gids.len; i++)
     {
       /* the last metric or the one for gids[i] */
@@ -138,7 +140,14 @@ struct hmtxvmtx
       }
       else
       {
-        FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
+	if (gids[i] >= _mtx.num_metrics)
+	{
+	  DEBUG_MSG(SUBSET, nullptr, "gid %d is >= number of source metrics %d",
+		    gids[i], _mtx.num_metrics);
+	  failed = true;
+	  break;
+	}
+	FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
         if (i < num_advances)
         {
           /* dest needs a full LongMetric */
@@ -157,7 +166,7 @@ struct hmtxvmtx
     _mtx.fini ();
 
     // Amend header num hmetrics
-    if (unlikely (!subset_update_header (plan, num_advances)))
+    if (failed || unlikely (!subset_update_header (plan, num_advances)))
     {
       free (dest);
       return false;
diff --git a/test/api/test-subset-hmtx.c b/test/api/test-subset-hmtx.c
index cb224972..0ed62562 100644
--- a/test/api/test-subset-hmtx.c
+++ b/test/api/test-subset-hmtx.c
@@ -163,7 +163,8 @@ test_subset_invalid_hmtx (void)
 
   hb_subset_profile_t *profile = hb_subset_profile_create();
   hb_face_t *subset = hb_subset (face, profile, input);
-  g_assert (!subset);
+  g_assert (subset);
+  g_assert (subset == hb_face_get_empty ());
 
   hb_subset_input_destroy (input);
   hb_subset_profile_destroy (profile);
commit 31281d6a17a03a124456a4cab54e31b248b41267
Author: Garret Rieger <grieger at google.com>
Date:   Mon Mar 19 17:47:57 2018 -0700

    [subset] Add a test demonstrating a seg fault while subsetting hmtx.

diff --git a/test/api/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480 b/test/api/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480
new file mode 100644
index 00000000..890c4498
Binary files /dev/null and b/test/api/fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480 differ
diff --git a/test/api/test-subset-hmtx.c b/test/api/test-subset-hmtx.c
index fc57718a..cb224972 100644
--- a/test/api/test-subset-hmtx.c
+++ b/test/api/test-subset-hmtx.c
@@ -150,6 +150,27 @@ test_subset_hmtx_noop (void)
   hb_face_destroy (face_abc);
 }
 
+static void
+test_subset_invalid_hmtx (void)
+{
+  hb_face_t *face = hb_subset_test_open_font("fonts/crash-e4e0bb1458a91b692eba492c907ae1f94e635480");
+
+  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
+  hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'b');
+  hb_set_add (codepoints, 'c');
+
+  hb_subset_profile_t *profile = hb_subset_profile_create();
+  hb_face_t *subset = hb_subset (face, profile, input);
+  g_assert (!subset);
+
+  hb_subset_input_destroy (input);
+  hb_subset_profile_destroy (profile);
+  hb_face_destroy (subset);
+  hb_face_destroy (face);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -160,6 +181,7 @@ main (int argc, char **argv)
   hb_test_add (test_subset_hmtx_keep_num_metrics);
   hb_test_add (test_subset_hmtx_decrease_num_metrics);
   hb_test_add (test_subset_hmtx_noop);
+  hb_test_add (test_subset_invalid_hmtx);
 
   return hb_test_run();
 }
commit b5c7d6cffc2098dafa06822b28a5fd4f6218b60c
Author: Garret Rieger <grieger at google.com>
Date:   Fri Mar 16 10:20:21 2018 -0700

    [subset] Restore subset to hb-subset-fuzzer.

diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index dc9f9016..a57f41dc 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -55,7 +55,7 @@ hb_subset_fuzzer_SOURCES = \
 	main.cc \
 	$(NULL)
 hb_subset_fuzzer_LDADD = \
-	$(top_builddir)/src/libharfbuzz-fuzzing.la \
+	$(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
 	$(NULL)
 hb_subset_fuzzer_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index c59a8e28..1e26d26a 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -9,7 +9,6 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
   printf ("hb-subset-fuzzer: input size = %zu\n", size);
-  /*
   hb_blob_t *blob = hb_blob_create ((const char *)data, size,
                                     HB_MEMORY_MODE_READONLY, NULL, NULL);
   hb_face_t *face = hb_face_create (blob, 0);
@@ -35,7 +34,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
   hb_subset_profile_destroy (profile);
   hb_face_destroy (face);
   hb_blob_destroy (blob);
-  */
 
   return 0;
 }
commit 957e7756634a4fdf1654041e20e883cf964ecac9
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Mar 19 12:19:42 2018 +0330

    [dwrite] Use new again and enable the build on msys2 bots (#890)

diff --git a/appveyor.yml b/appveyor.yml
index 5971337c..b6857206 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -20,11 +20,11 @@ environment:
 
 
     - compiler: msys2
-      MINGW_PREFIX: /c/msys2/mingw64/
+      MINGW_PREFIX: /mingw64
       MINGW_CHOST: x86_64-w64-mingw32
       MSYS2_ARCH: x86_64
     - compiler: msys2
-      MINGW_PREFIX: /c/msys2/mingw32/
+      MINGW_PREFIX: /mingw32
       MINGW_CHOST: i686-w64-mingw32
       MSYS2_ARCH: i686
 
@@ -44,7 +44,8 @@ build_script:
   - 'if "%compiler%"=="msvc" if not "%platform%"=="ARM" ctest --output-on-failure -C %configuration%'
 
   - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-$MSYS2_ARCH-{freetype,cairo,icu,gettext,gobject-introspection,gcc,gcc-libs,glib2,graphite2,pkg-config,python2}"'
-  - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || .ci/fail.sh"'
+  - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "curl https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-headers/include/dwrite_1.h?format=raw > %MINGW_PREFIX%/%MINGW_CHOST%/include/dwrite_1.h"'
+  - 'if "%compiler%"=="msys2" C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; PATH=$PATH:/mingw64/bin:/mingw32/bin; ./autogen.sh --with-uniscribe --with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2 --with-directwrite --build=%MINGW_CHOST% --host=%MINGW_CHOST% --prefix=%MINGW_PREFIX%; make; make check || .ci/fail.sh"'
 
 cache:
   - c:\tools\vcpkg\installed\
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index 40e9e39b..0d3b1c2e 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -48,7 +48,7 @@ class DWriteFontFileLoader : public IDWriteFontFileLoader
 private:
   IDWriteFontFileStream *mFontFileStream;
 public:
-  void init (IDWriteFontFileStream *fontFileStream)
+  DWriteFontFileLoader (IDWriteFontFileStream *fontFileStream)
   {
     mFontFileStream = fontFileStream;
   }
@@ -74,7 +74,7 @@ private:
   uint8_t *mData;
   uint32_t mSize;
 public:
-  void init (uint8_t *aData, uint32_t aSize)
+  DWriteFontFileStream (uint8_t *aData, uint32_t aSize)
   {
     mData = aData;
     mSize = aSize;
@@ -151,14 +151,11 @@ _hb_directwrite_shaper_face_data_create(hb_face_t *face)
 
   HRESULT hr;
   hb_blob_t *blob = hb_face_reference_blob (face);
-  DWriteFontFileStream *fontFileStream = (DWriteFontFileStream*)
-    malloc (sizeof (DWriteFontFileStream));
-  fontFileStream->init ((uint8_t*) hb_blob_get_data (blob, nullptr),
+  DWriteFontFileStream *fontFileStream = new DWriteFontFileStream (
+    (uint8_t *) hb_blob_get_data (blob, nullptr),
     hb_blob_get_length (blob));
 
-  DWriteFontFileLoader *fontFileLoader = (DWriteFontFileLoader*)
-    malloc (sizeof (DWriteFontFileLoader));
-  fontFileLoader->init (fontFileStream);
+  DWriteFontFileLoader *fontFileLoader = new DWriteFontFileLoader (fontFileStream);
   dwriteFactory->RegisterFontFileLoader (fontFileLoader);
 
   IDWriteFontFile *fontFile;
@@ -216,9 +213,9 @@ _hb_directwrite_shaper_face_data_destroy(hb_directwrite_shaper_face_data_t *data
     data->dwriteFactory->Release ();
   }
   if (data->fontFileLoader)
-    free (data->fontFileLoader);
+    delete data->fontFileLoader;
   if (data->fontFileStream)
-    free (data->fontFileStream);
+    delete data->fontFileStream;
   if (data->faceBlob)
     hb_blob_destroy (data->faceBlob);
   if (data)
@@ -924,7 +921,7 @@ hb_directwrite_shape_experimental_width(hb_font_t          *font,
   unsigned int        num_features,
   float               width)
 {
-  static char *shapers = (char *) "directwrite";
+  static const char *shapers = "directwrite";
   hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face,
     &buffer->props, features, num_features, &shapers);
   hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer,
commit 8d1b4082ae01b8fd87b2e83c89f670c1c7cfa0b1
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Sat Mar 17 01:05:03 2018 +0330

    Appropriate fix for msys2 bot fail on gen-def.py (#894)

diff --git a/src/Makefile.am b/src/Makefile.am
index d9947880..a81f1125 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -243,7 +243,7 @@ DISTCLEANFILES += \
 	$(HB_GOBJECT_ENUM_headers) \
 	$(NULL)
 hb-gobject-enums.%: hb-gobject-enums.%.tmpl $(HBHEADERS)
-	$(AM_V_GEN) $(GLIB_MKENUMS) \
+	$(AM_V_GEN) PYTHONIOENCODING=UTF-8 $(GLIB_MKENUMS) \
 		--identifier-prefix hb_ --symbol-prefix hb_gobject \
 		--template $^ | \
 	sed 's/_t_get_type/_get_type/g; s/_T (/ (/g' > "$@" \
diff --git a/src/gen-def.py b/src/gen-def.py
index 74507e46..de35eb7d 100755
--- a/src/gen-def.py
+++ b/src/gen-def.py
@@ -7,7 +7,7 @@ import io, os, re, sys
 headers_content = []
 for h in os.environ["headers"].split (' '):
 	if h.endswith (".h"):
-		with io.open (h, encoding='ISO-8859-1') as f: headers_content.append (f.read ())
+		with io.open (h, encoding='utf-8') as f: headers_content.append (f.read ())
 
 result = """EXPORTS
 %s
commit 7b4333b090a3adf04519ec853456cafff07dedf0
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Mar 16 22:45:09 2018 +0330

    Do feature test before adding -Bsymbolic-functions, autotools part (#892)

diff --git a/configure.ac b/configure.ac
index 2831e599..9e3bf081 100644
--- a/configure.ac
+++ b/configure.ac
@@ -94,7 +94,7 @@ AC_CHECK_ALIGNOF([struct{char;}])
 if test "x$GCC" = "xyes"; then
 
 	# Make symbols link locally
-	LDFLAGS="$LDFLAGS -Bsymbolic-functions"
+	AX_CHECK_LINK_FLAG([[-Bsymbolic-functions]], [LDFLAGS="$LDFLAGS -Bsymbolic-functions"])
 
 	# Assorted warnings
 	CXXFLAGS="$CXXFLAGS -Wcast-align"
diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4
new file mode 100644
index 00000000..819409a2
--- /dev/null
+++ b/m4/ax_check_link_flag.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+#    https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the linker or gives an error.
+#   (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the linker's default flags
+#   when the check is done.  The check is thus made with the flags: "LDFLAGS
+#   EXTRA-FLAGS FLAG".  This can for example be used to force the linker to
+#   issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_LINK_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans at gmail.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+  ax_check_save_flags=$LDFLAGS
+  LDFLAGS="$LDFLAGS $4 $1"
+  AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  LDFLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS
commit d68f00e4d8b061f56d3bd46d5ed1bc51406a4f1a
Author: Joel Winarske <joel.winarske at gmail.com>
Date:   Fri Mar 16 12:14:27 2018 -0700

    Do feature test before adding -Bsymbolic-functions, cmake part (#889)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ddc15a7..85709b2e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -537,7 +537,11 @@ target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
 
 if (UNIX OR MINGW)
   # Make symbols link locally
-  link_libraries(-Bsymbolic-functions)
+  include(CheckCXXCompilerFlag)
+  check_cxx_compiler_flag(-Bsymbolic-functions CXX_SUPPORTS_FLAG_BSYMB_FUNCS)
+  if(CXX_SUPPORTS_FLAG_BSYMB_FUNCS)
+    link_libraries(-Bsymbolic-functions)
+  endif()  
 
   if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
     # Make sure we don't link to libstdc++
commit 42d3271cc39050c9df5f8c7345322ae90592158e
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Mar 16 22:39:58 2018 +0330

    [cmake] Don't hide symbols by default (#891)
    
    But keep use of cmake idiomatic way of making inlines hidden

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b9796ebf..5ddc15a7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,4 @@
 cmake_minimum_required(VERSION 2.8.0)
-# Allow symbol hiding for both static and shared libs.
-cmake_policy(SET CMP0063 NEW)
-
 project(harfbuzz)
 
 enable_testing()
@@ -528,8 +525,6 @@ endif ()
 ## Define harfbuzz library
 add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers})
 set_target_properties(harfbuzz PROPERTIES
-  C_VISIBILITY_PRESET hidden
-  CXX_VISIBILITY_PRESET hidden
   VISIBILITY_INLINES_HIDDEN TRUE)
 target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
 
@@ -537,8 +532,6 @@ target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
 add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
 add_dependencies(harfbuzz-subset harfbuzz)
 set_target_properties(harfbuzz-subset PROPERTIES
-  C_VISIBILITY_PRESET hidden
-  CXX_VISIBILITY_PRESET hidden
   VISIBILITY_INLINES_HIDDEN TRUE)
 target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
 
@@ -568,20 +561,14 @@ if (HB_HAVE_GOBJECT)
     ${hb_gobject_gen_headers}
   )
   set_target_properties(harfbuzz-gobject PROPERTIES
-    C_VISIBILITY_PRESET hidden
-    CXX_VISIBILITY_PRESET hidden
     VISIBILITY_INLINES_HIDDEN TRUE)
   include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/src)
   add_dependencies(harfbuzz-gobject harfbuzz)
   target_link_libraries(harfbuzz-gobject harfbuzz ${GOBJECT_LIBRARIES} ${THIRD_PARTY_LIBS})
 endif ()
 
-if (BUILD_SHARED_LIBS)
-  if (WIN32 AND NOT MINGW)
-    add_definitions("-DHB_EXTERN=__declspec(dllexport) extern")
-  else ()
-    add_definitions("-DHB_EXTERN=__attribute__(( visibility( \"default\" ) )) extern")
-  endif ()
+if (BUILD_SHARED_LIBS AND WIN32 AND NOT MINGW)
+  add_definitions("-DHB_EXTERN=__declspec(dllexport) extern")
 endif ()
 
 # On Windows, g-ir-scanner requires a DLL build in order for it to work
commit 584693e0cb3585a910b18d7916d7e554ecdf619a
Author: Garret Rieger <grieger at google.com>
Date:   Thu Mar 15 18:27:01 2018 -0700

    [subset] Test not linking libharfbuzz-subset-fuzzing into hb-subset-fuzzer.

diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index a57f41dc..dc9f9016 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -55,7 +55,7 @@ hb_subset_fuzzer_SOURCES = \
 	main.cc \
 	$(NULL)
 hb_subset_fuzzer_LDADD = \
-	$(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
+	$(top_builddir)/src/libharfbuzz-fuzzing.la \
 	$(NULL)
 hb_subset_fuzzer_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index 1e26d26a..c59a8e28 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -9,6 +9,7 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
   printf ("hb-subset-fuzzer: input size = %zu\n", size);
+  /*
   hb_blob_t *blob = hb_blob_create ((const char *)data, size,
                                     HB_MEMORY_MODE_READONLY, NULL, NULL);
   hb_face_t *face = hb_face_create (blob, 0);
@@ -34,6 +35,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
   hb_subset_profile_destroy (profile);
   hb_face_destroy (face);
   hb_blob_destroy (blob);
+  */
 
   return 0;
 }
diff --git a/test/fuzzing/run-subset-fuzzer-tests.py b/test/fuzzing/run-subset-fuzzer-tests.py
index b0bb52ce..229881a4 100755
--- a/test/fuzzing/run-subset-fuzzer-tests.py
+++ b/test/fuzzing/run-subset-fuzzer-tests.py
@@ -6,7 +6,7 @@ import sys, os, subprocess
 srcdir = os.environ.get ("srcdir", ".")
 EXEEXT = os.environ.get ("EXEEXT", "")
 top_builddir = os.environ.get ("top_builddir", ".")
-hb_subset_fuzzer = os.path.join (top_builddir, "hb-shape-fuzzer" + EXEEXT)
+hb_subset_fuzzer = os.path.join (top_builddir, "hb-subset-fuzzer" + EXEEXT)
 
 if not os.path.exists (hb_subset_fuzzer):
         if len (sys.argv) == 1 or not os.path.exists (sys.argv[1]):
commit 3f9361fe7a68896d2a5a44709ec08fe510144215
Author: Garret Rieger <grieger at google.com>
Date:   Thu Mar 15 18:06:15 2018 -0700

    [subset] Test hb-shape-fuzzer in run-subset-fuzzer-tests.

diff --git a/test/fuzzing/run-subset-fuzzer-tests.py b/test/fuzzing/run-subset-fuzzer-tests.py
index 229881a4..b0bb52ce 100755
--- a/test/fuzzing/run-subset-fuzzer-tests.py
+++ b/test/fuzzing/run-subset-fuzzer-tests.py
@@ -6,7 +6,7 @@ import sys, os, subprocess
 srcdir = os.environ.get ("srcdir", ".")
 EXEEXT = os.environ.get ("EXEEXT", "")
 top_builddir = os.environ.get ("top_builddir", ".")
-hb_subset_fuzzer = os.path.join (top_builddir, "hb-subset-fuzzer" + EXEEXT)
+hb_subset_fuzzer = os.path.join (top_builddir, "hb-shape-fuzzer" + EXEEXT)
 
 if not os.path.exists (hb_subset_fuzzer):
         if len (sys.argv) == 1 or not os.path.exists (sys.argv[1]):
commit ce368e0d05147e70d8ad90383d748644b07f1d6f
Author: Garret Rieger <grieger at google.com>
Date:   Thu Mar 15 18:04:54 2018 -0700

    [subset] make libharfbuzz-subset-fuzzing.la depend on lib target.

diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index 96b1cbf4..a57f41dc 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -11,6 +11,7 @@ lib:
 	@$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src fuzzing
 
 $(top_builddir)/src/libharfbuzz-fuzzing.la: lib
+$(top_builddir)/src/libharfbuzz-subset-fuzzing.la: lib
 
 EXTRA_DIST += \
 	README \
commit 85a57029cdad634f56aa3ccc768e72bcb03888e3
Author: Garret Rieger <grieger at google.com>
Date:   Thu Mar 15 16:31:38 2018 -0700

    [subset] %d -> %zu

diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index 863c495f..1e26d26a 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -8,7 +8,7 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
-  printf ("hb-subset-fuzzer: input size = %d\n", size);
+  printf ("hb-subset-fuzzer: input size = %zu\n", size);
   hb_blob_t *blob = hb_blob_create ((const char *)data, size,
                                     HB_MEMORY_MODE_READONLY, NULL, NULL);
   hb_face_t *face = hb_face_create (blob, 0);
commit 318eea585329807477aab4eec173b561a08a46ca
Author: Garret Rieger <grieger at google.com>
Date:   Thu Mar 15 16:14:01 2018 -0700

    [subset] Add some more logging to hb-subset-fuzzer.

diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index dfa83613..863c495f 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -8,6 +8,7 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
+  printf ("hb-subset-fuzzer: input size = %d\n", size);
   hb_blob_t *blob = hb_blob_create ((const char *)data, size,
                                     HB_MEMORY_MODE_READONLY, NULL, NULL);
   hb_face_t *face = hb_face_create (blob, 0);
commit 64bab8b3d009ed4327c2db9fa3425682de225810
Author: Garret Rieger <grieger at google.com>
Date:   Thu Mar 15 16:12:00 2018 -0700

    [subset] Fix run-shape-fuzzer-tests.py. It was generating incorrect paths for input fonts.

diff --git a/test/fuzzing/run-shape-fuzzer-tests.py b/test/fuzzing/run-shape-fuzzer-tests.py
index 088b36a4..43378d1b 100755
--- a/test/fuzzing/run-shape-fuzzer-tests.py
+++ b/test/fuzzing/run-shape-fuzzer-tests.py
@@ -19,10 +19,12 @@ please provide it as the first argument to the tool""")
 print ('hb_shape_fuzzer:', hb_shape_fuzzer)
 fails = 0
 
-for line in open (os.path.join (srcdir, "..", "shaping", "data", "in-house", "tests", "fuzzed.tests")):
+parent_path = os.path.join (srcdir, "..", "shaping", "data", "in-house", "tests")
+for line in open (os.path.join (parent_path, "fuzzed.tests")):
 	font = line.split (":")[0]
+	font_path = os.path.join (parent_path, font)
 
-	p = subprocess.Popen ([hb_shape_fuzzer, os.path.join (srcdir, "..", "shaping", font)])
+	p = subprocess.Popen ([hb_shape_fuzzer, font_path])
 
 	if p.wait () != 0:
 		fails = fails + 1
commit 6f9a584371ba4a9a63be3fa89f46474047a43ceb
Author: Garret Rieger <grieger at google.com>
Date:   Thu Mar 15 15:41:08 2018 -0700

    [subset] Add more verbose output for subset fuzzer test.

diff --git a/test/fuzzing/run-shape-fuzzer-tests.py b/test/fuzzing/run-shape-fuzzer-tests.py
index bf461acf..088b36a4 100755
--- a/test/fuzzing/run-shape-fuzzer-tests.py
+++ b/test/fuzzing/run-shape-fuzzer-tests.py
@@ -28,5 +28,5 @@ for line in open (os.path.join (srcdir, "..", "shaping", "data", "in-house", "te
 		fails = fails + 1
 
 if fails:
-	print ("%i fuzzer related tests failed." % fails)
+	print ("%i shape fuzzer related tests failed." % fails)
 	sys.exit (1)
diff --git a/test/fuzzing/run-subset-fuzzer-tests.py b/test/fuzzing/run-subset-fuzzer-tests.py
index 9450cb43..229881a4 100755
--- a/test/fuzzing/run-subset-fuzzer-tests.py
+++ b/test/fuzzing/run-subset-fuzzer-tests.py
@@ -20,12 +20,16 @@ print ('hb_subset_fuzzer:', hb_subset_fuzzer)
 fails = 0
 
 parent_path = os.path.join (srcdir, "..", "subset", "data", "fonts")
+print ("running subset fuzzer against fonts in %s" % parent_path)
 for file in os.listdir (parent_path):
-        p = subprocess.Popen ([hb_subset_fuzzer, os.path.join(parent_path, file)])
+        path = os.path.join(parent_path, file)
+        print ("running subset fuzzer against %s" % path)
+        p = subprocess.Popen ([hb_subset_fuzzer, path])
 
         if p.wait () != 0:
+                print ("failed for %s" % path)
                 fails = fails + 1
 
 if fails:
-        print ("%i fuzzer related tests failed." % fails)
+        print ("%i subset fuzzer related tests failed." % fails)
         sys.exit (1)
commit 0ce0f8781213f8f01b9ebc8cfa31434784899952
Author: Garret Rieger <grieger at google.com>
Date:   Thu Mar 15 13:04:31 2018 -0700

    [subset] Rename hb-fuzzer -> hb-shape-fuzzer.

diff --git a/test/fuzzing/CMakeLists.txt b/test/fuzzing/CMakeLists.txt
index cb41dc18..577d13ce 100644
--- a/test/fuzzing/CMakeLists.txt
+++ b/test/fuzzing/CMakeLists.txt
@@ -1,25 +1,25 @@
 if (HB_CHECK)
   file (READ "${CMAKE_CURRENT_SOURCE_DIR}/Makefile.am" MAKEFILEAM)
-  extract_make_variable (hb_fuzzer_SOURCES ${MAKEFILEAM})
+  extract_make_variable (hb_shape_fuzzer_SOURCES ${MAKEFILEAM})
   extract_make_variable (hb_subset_fuzzer_SOURCES ${MAKEFILEAM})
 
   # TODO: enable these two
   #extract_make_variable (FUZZING_CPPFLAGS ${MAKEFILEAM}) # extracting regex fail
-  #add_executable (hb-fuzzer # it should be run only after ragel execution
+  #add_executable (hb-shape-fuzzer # it should be run only after ragel execution
   #  ${project_sources} ${project_extra_sources} ${project_headers}
-  #  ${hb_fuzzer_SOURCES})
+  #  ${hb_shape_fuzzer_SOURCES})
 
-  add_executable (hb-fuzzer ${hb_fuzzer_SOURCES})
-  target_link_libraries (hb-fuzzer harfbuzz)
+  add_executable (hb-shape-fuzzer ${hb_shape_fuzzer_SOURCES})
+  target_link_libraries (hb-shape-fuzzer harfbuzz)
 
   add_executable (hb-subset-fuzzer ${hb_subset_fuzzer_SOURCES})
   target_link_libraries (hb-subset-fuzzer harfbuzz-subset)
 
-  target_compile_definitions(hb-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
+  target_compile_definitions(hb-shape-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
   target_compile_definitions(hb-subset-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
 
-  add_test (NAME hb-fuzzer
-    COMMAND "${PYTHON_EXECUTABLE}" run-fuzzer-tests.py $<TARGET_FILE:hb-fuzzer>
+  add_test (NAME hb-shape-fuzzer
+    COMMAND "${PYTHON_EXECUTABLE}" run-shape-fuzzer-tests.py $<TARGET_FILE:hb-shape-fuzzer>
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
   add_test (NAME hb-subset-fuzzer
     COMMAND "${PYTHON_EXECUTABLE}" run-subset-fuzzer-tests.py $<TARGET_FILE:hb-subset-fuzzer>
diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index 06488206..96b1cbf4 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -14,13 +14,13 @@ $(top_builddir)/src/libharfbuzz-fuzzing.la: lib
 
 EXTRA_DIST += \
 	README \
-	run-fuzzer-tests.py \
+	run-shape-fuzzer-tests.py \
 	run-subset-fuzzer-tests.py \
 	CMakeLists.txt \
 	$(NULL)
 
 check_PROGRAMS = \
-	hb-fuzzer \
+	hb-shape-fuzzer \
 	hb-subset-fuzzer \
 	$(NULL)
 
@@ -33,18 +33,18 @@ LDADD = \
 	$(top_builddir)/src/libharfbuzz-fuzzing.la \
 	$(NULL)
 
-hb_fuzzer_SOURCES = \
+hb_shape_fuzzer_SOURCES = \
 	hb-fuzzer.hh \
-	hb-fuzzer.cc \
+	hb-shape-fuzzer.cc \
 	main.cc \
 	$(NULL)
-hb_fuzzer_LDADD = \
+hb_shape_fuzzer_LDADD = \
 	$(LDADD) \
 	$(NULL)
-hb_fuzzer_CPPFLAGS = \
+hb_shape_fuzzer_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	$(NULL)
-hb_fuzzer_DEPENDENCIES = \
+hb_shape_fuzzer_DEPENDENCIES = \
 	lib \
 	$(NULL)
 
@@ -64,7 +64,7 @@ hb_subset_fuzzer_DEPENDENCIES = \
 	$(NULL)
 
 check:
-	EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-fuzzer-tests.py
+	EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-shape-fuzzer-tests.py
 	EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-subset-fuzzer-tests.py
 
 -include $(top_srcdir)/git.mk
diff --git a/test/fuzzing/hb-fuzzer.cc b/test/fuzzing/hb-shape-fuzzer.cc
similarity index 100%
rename from test/fuzzing/hb-fuzzer.cc
rename to test/fuzzing/hb-shape-fuzzer.cc
diff --git a/test/fuzzing/run-fuzzer-tests.py b/test/fuzzing/run-shape-fuzzer-tests.py
similarity index 64%
rename from test/fuzzing/run-fuzzer-tests.py
rename to test/fuzzing/run-shape-fuzzer-tests.py
index 9455a4b6..bf461acf 100755
--- a/test/fuzzing/run-fuzzer-tests.py
+++ b/test/fuzzing/run-shape-fuzzer-tests.py
@@ -6,23 +6,23 @@ import sys, os, subprocess
 srcdir = os.environ.get ("srcdir", ".")
 EXEEXT = os.environ.get ("EXEEXT", "")
 top_builddir = os.environ.get ("top_builddir", ".")
-hb_fuzzer = os.path.join (top_builddir, "hb-fuzzer" + EXEEXT)
+hb_shape_fuzzer = os.path.join (top_builddir, "hb-shape-fuzzer" + EXEEXT)
 
-if not os.path.exists (hb_fuzzer):
+if not os.path.exists (hb_shape_fuzzer):
 	if len (sys.argv) == 1 or not os.path.exists (sys.argv[1]):
-		print ("""Failed to find hb-fuzzer binary automatically,
+		print ("""Failed to find hb-shape-fuzzer binary automatically,
 please provide it as the first argument to the tool""")
 		sys.exit (1)
 
-	hb_fuzzer = sys.argv[1]
+	hb_shape_fuzzer = sys.argv[1]
 
-print ('hb_fuzzer:', hb_fuzzer)
+print ('hb_shape_fuzzer:', hb_shape_fuzzer)
 fails = 0
 
 for line in open (os.path.join (srcdir, "..", "shaping", "data", "in-house", "tests", "fuzzed.tests")):
 	font = line.split (":")[0]
 
-	p = subprocess.Popen ([hb_fuzzer, os.path.join (srcdir, "..", "shaping", font)])
+	p = subprocess.Popen ([hb_shape_fuzzer, os.path.join (srcdir, "..", "shaping", font)])
 
 	if p.wait () != 0:
 		fails = fails + 1
commit 1e9bd6d5ff0af0189b6398c5e13cff11ee70762b
Author: Garret Rieger <grieger at google.com>
Date:   Wed Mar 14 19:58:15 2018 -0700

    [subset] Add rub-subset-fuzzer-tests.py to dist files.

diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index d1f49e57..06488206 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -15,6 +15,7 @@ $(top_builddir)/src/libharfbuzz-fuzzing.la: lib
 EXTRA_DIST += \
 	README \
 	run-fuzzer-tests.py \
+	run-subset-fuzzer-tests.py \
 	CMakeLists.txt \
 	$(NULL)
 
commit 474afaafd908a9c8174e05d693ac214ef2cc2597
Author: Garret Rieger <grieger at google.com>
Date:   Wed Mar 14 19:15:33 2018 -0700

    [subset] Add a test runner for hb-subset-fuzzer and cmake build config.

diff --git a/test/fuzzing/CMakeLists.txt b/test/fuzzing/CMakeLists.txt
index fe4cf790..cb41dc18 100644
--- a/test/fuzzing/CMakeLists.txt
+++ b/test/fuzzing/CMakeLists.txt
@@ -1,6 +1,7 @@
 if (HB_CHECK)
   file (READ "${CMAKE_CURRENT_SOURCE_DIR}/Makefile.am" MAKEFILEAM)
   extract_make_variable (hb_fuzzer_SOURCES ${MAKEFILEAM})
+  extract_make_variable (hb_subset_fuzzer_SOURCES ${MAKEFILEAM})
 
   # TODO: enable these two
   #extract_make_variable (FUZZING_CPPFLAGS ${MAKEFILEAM}) # extracting regex fail
@@ -11,8 +12,16 @@ if (HB_CHECK)
   add_executable (hb-fuzzer ${hb_fuzzer_SOURCES})
   target_link_libraries (hb-fuzzer harfbuzz)
 
+  add_executable (hb-subset-fuzzer ${hb_subset_fuzzer_SOURCES})
+  target_link_libraries (hb-subset-fuzzer harfbuzz-subset)
+
   target_compile_definitions(hb-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
+  target_compile_definitions(hb-subset-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
+
   add_test (NAME hb-fuzzer
     COMMAND "${PYTHON_EXECUTABLE}" run-fuzzer-tests.py $<TARGET_FILE:hb-fuzzer>
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+  add_test (NAME hb-subset-fuzzer
+    COMMAND "${PYTHON_EXECUTABLE}" run-subset-fuzzer-tests.py $<TARGET_FILE:hb-subset-fuzzer>
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 endif ()
diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index 27f59d9d..d1f49e57 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -48,7 +48,7 @@ hb_fuzzer_DEPENDENCIES = \
 	$(NULL)
 
 hb_subset_fuzzer_SOURCES = \
-	hb-subset.hh \
+	hb-fuzzer.hh \
 	hb-subset-fuzzer.cc \
 	main.cc \
 	$(NULL)
@@ -64,5 +64,6 @@ hb_subset_fuzzer_DEPENDENCIES = \
 
 check:
 	EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-fuzzer-tests.py
+	EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-subset-fuzzer-tests.py
 
 -include $(top_srcdir)/git.mk
diff --git a/test/fuzzing/run-subset-fuzzer-tests.py b/test/fuzzing/run-subset-fuzzer-tests.py
new file mode 100755
index 00000000..9450cb43
--- /dev/null
+++ b/test/fuzzing/run-subset-fuzzer-tests.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+import sys, os, subprocess
+
+srcdir = os.environ.get ("srcdir", ".")
+EXEEXT = os.environ.get ("EXEEXT", "")
+top_builddir = os.environ.get ("top_builddir", ".")
+hb_subset_fuzzer = os.path.join (top_builddir, "hb-subset-fuzzer" + EXEEXT)
+
+if not os.path.exists (hb_subset_fuzzer):
+        if len (sys.argv) == 1 or not os.path.exists (sys.argv[1]):
+                print ("""Failed to find hb-subset-fuzzer binary automatically,
+please provide it as the first argument to the tool""")
+                sys.exit (1)
+
+        hb_subset_fuzzer = sys.argv[1]
+
+print ('hb_subset_fuzzer:', hb_subset_fuzzer)
+fails = 0
+
+parent_path = os.path.join (srcdir, "..", "subset", "data", "fonts")
+for file in os.listdir (parent_path):
+        p = subprocess.Popen ([hb_subset_fuzzer, os.path.join(parent_path, file)])
+
+        if p.wait () != 0:
+                fails = fails + 1
+
+if fails:
+        print ("%i fuzzer related tests failed." % fails)
+        sys.exit (1)
commit aa9612d35f59f7f269fba4797c8da491844c56ec
Author: Garret Rieger <grieger at google.com>
Date:   Mon Mar 12 18:04:34 2018 -0700

    [subset] Fix fuzzing build for hb-subset-fuzzer.

diff --git a/src/Makefile.am b/src/Makefile.am
index 4d1f237d..d9947880 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -184,7 +184,8 @@ FUZZING_CPPFLAGS = \
 	-DHB_BUFFER_MAX_OPS_MIN=64 \
 	-DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
 	$(NULL)
-EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la
+EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la
+
 libharfbuzz_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_fuzzing_la_LDFLAGS)
 libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES)
 libharfbuzz_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS)
@@ -193,23 +194,9 @@ libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
 EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
 CLEANFILES += libharfbuzz-fuzzing.la
 
-SUBSET_FUZZING_CPPFLAGS = \
-	-DHB_NDEBUG \
-	-DHB_MAX_NESTING_LEVEL=3 \
-	-DHB_SANITIZE_MAX_EDITS=3 \
-	-DHB_SANITIZE_MAX_OPS_FACTOR=3 \
-	-DHB_SANITIZE_MAX_OPS_MIN=128 \
-	-DHB_BUFFER_MAX_LEN_FACTOR=3 \
-	-DHB_BUFFER_MAX_LEN_MIN=8 \
-	-DHB_BUFFER_MAX_LEN_DEFAULT=128 \
-	-DHB_BUFFER_MAX_OPS_FACTOR=8 \
-	-DHB_BUFFER_MAX_OPS_MIN=64 \
-	-DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
-	$(NULL)
-EXTRA_LTLIBRARIES = libharfbuzz-subset-fuzzing.la
 libharfbuzz_subset_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_subset_fuzzing_la_LDFLAGS)
 libharfbuzz_subset_fuzzing_la_SOURCES = $(libharfbuzz_subset_la_SOURCES)
-libharfbuzz_subset_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(SUBSET_FUZZING_CPPFLAGS)
+libharfbuzz_subset_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS)
 libharfbuzz_subset_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
 libharfbuzz_subset_fuzzing_la_LIBADD = $(libharfbuzz_subset_la_LIBADD)
 EXTRA_libharfbuzz_subset_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_subset_la_DEPENDENCIES)
diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index 638f2f0d..27f59d9d 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -50,6 +50,7 @@ hb_fuzzer_DEPENDENCIES = \
 hb_subset_fuzzer_SOURCES = \
 	hb-subset.hh \
 	hb-subset-fuzzer.cc \
+	main.cc \
 	$(NULL)
 hb_subset_fuzzer_LDADD = \
 	$(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
commit b674fc1f9fa36857214ddaba3d32877f03ffec8c
Author: Garret Rieger <grieger at google.com>
Date:   Mon Mar 12 16:33:47 2018 -0700

    [subset] Add missing destroy of subsetting result in subset fuzzer.

diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index 3081a57c..dfa83613 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -28,6 +28,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 
   hb_face_t *result = hb_subset (face, profile, input);
 
+  hb_face_destroy (result);
   hb_subset_input_destroy (input);
   hb_subset_profile_destroy (profile);
   hb_face_destroy (face);
commit 1beb08862e9bd668599f0385d7ba59272fc24912
Author: Garret Rieger <grieger at google.com>
Date:   Mon Mar 12 16:08:16 2018 -0700

    [subset] First pass at setting up a fuzzing program for hb-subset.

diff --git a/src/Makefile.am b/src/Makefile.am
index afa104b8..4d1f237d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,7 +17,7 @@ check_PROGRAMS =
 
 # Convenience targets:
 lib: $(BUILT_SOURCES) libharfbuzz.la libharfbuzz-subset.la
-fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la
+fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la
 
 lib_LTLIBRARIES = libharfbuzz.la
 
@@ -193,6 +193,28 @@ libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD)
 EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES)
 CLEANFILES += libharfbuzz-fuzzing.la
 
+SUBSET_FUZZING_CPPFLAGS = \
+	-DHB_NDEBUG \
+	-DHB_MAX_NESTING_LEVEL=3 \
+	-DHB_SANITIZE_MAX_EDITS=3 \
+	-DHB_SANITIZE_MAX_OPS_FACTOR=3 \
+	-DHB_SANITIZE_MAX_OPS_MIN=128 \
+	-DHB_BUFFER_MAX_LEN_FACTOR=3 \
+	-DHB_BUFFER_MAX_LEN_MIN=8 \
+	-DHB_BUFFER_MAX_LEN_DEFAULT=128 \
+	-DHB_BUFFER_MAX_OPS_FACTOR=8 \
+	-DHB_BUFFER_MAX_OPS_MIN=64 \
+	-DHB_BUFFER_MAX_OPS_DEFAULT=1024 \
+	$(NULL)
+EXTRA_LTLIBRARIES = libharfbuzz-subset-fuzzing.la
+libharfbuzz_subset_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_subset_fuzzing_la_LDFLAGS)
+libharfbuzz_subset_fuzzing_la_SOURCES = $(libharfbuzz_subset_la_SOURCES)
+libharfbuzz_subset_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(SUBSET_FUZZING_CPPFLAGS)
+libharfbuzz_subset_fuzzing_la_LDFLAGS = $(AM_LDFLAGS)
+libharfbuzz_subset_fuzzing_la_LIBADD = $(libharfbuzz_subset_la_LIBADD)
+EXTRA_libharfbuzz_subset_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_subset_la_DEPENDENCIES)
+CLEANFILES += libharfbuzz-subset-fuzzing.la
+
 if HAVE_ICU
 if HAVE_ICU_BUILTIN
 HBCFLAGS += $(ICU_CFLAGS)
diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index a7f73623..638f2f0d 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -20,6 +20,7 @@ EXTRA_DIST += \
 
 check_PROGRAMS = \
 	hb-fuzzer \
+	hb-subset-fuzzer \
 	$(NULL)
 
 AM_CPPFLAGS = \
@@ -46,6 +47,20 @@ hb_fuzzer_DEPENDENCIES = \
 	lib \
 	$(NULL)
 
+hb_subset_fuzzer_SOURCES = \
+	hb-subset.hh \
+	hb-subset-fuzzer.cc \
+	$(NULL)
+hb_subset_fuzzer_LDADD = \
+	$(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
+	$(NULL)
+hb_subset_fuzzer_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	$(NULL)
+hb_subset_fuzzer_DEPENDENCIES = \
+	lib \
+	$(NULL)
+
 check:
 	EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-fuzzer-tests.py
 
diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
new file mode 100644
index 00000000..3081a57c
--- /dev/null
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -0,0 +1,37 @@
+#include "hb-fuzzer.hh"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "hb-subset.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+  hb_blob_t *blob = hb_blob_create ((const char *)data, size,
+                                    HB_MEMORY_MODE_READONLY, NULL, NULL);
+  hb_face_t *face = hb_face_create (blob, 0);
+  hb_subset_profile_t *profile = hb_subset_profile_create ();
+  // TODO(grieger): Loop through common profiles (hints, no hints, etc.)
+  hb_subset_input_t *input = hb_subset_input_create_or_fail ();
+  hb_set_t *codepoints = hb_subset_input_unicode_set (input);
+
+  const hb_codepoint_t text[] =
+      {
+        'A', 'B', 'C', 'D', 'E', 'X', 'Y', 'Z', '1', '2',
+        '3', '@', '_', '%', '&', ')', '*', '$', '!'
+      };
+  for (int i = 0; i < sizeof (text) / sizeof (hb_codepoint_t); i++)
+  {
+    hb_set_add (codepoints, text[i]);
+  }
+
+  hb_face_t *result = hb_subset (face, profile, input);
+
+  hb_subset_input_destroy (input);
+  hb_subset_profile_destroy (profile);
+  hb_face_destroy (face);
+  hb_blob_destroy (blob);
+
+  return 0;
+}


More information about the HarfBuzz mailing list