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

Behdad Esfahbod behdad at kemper.freedesktop.org
Sat Apr 28 00:17:18 UTC 2018


 TODO                                                                             |    2 
 docs/harfbuzz-sections.txt                                                       |    1 
 src/dump-emoji.cc                                                                |   33 --
 src/dump-fon.cc                                                                  |   11 
 src/hb-aat-fmtx-table.hh                                                         |    2 
 src/hb-aat-gcid-table.hh                                                         |    2 
 src/hb-aat-layout-ankr-table.hh                                                  |    7 
 src/hb-aat-layout-bsln-table.hh                                                  |    9 
 src/hb-aat-layout-feat-table.hh                                                  |   10 
 src/hb-aat-layout-kerx-table.hh                                                  |   54 ++--
 src/hb-aat-layout-trak-table.hh                                                  |   27 +-
 src/hb-aat-ltag-table.hh                                                         |    2 
 src/hb-blob.cc                                                                   |  132 +++++++++-
 src/hb-blob.h                                                                    |    2 
 src/hb-coretext.cc                                                               |    4 
 src/hb-dsalgs.hh                                                                 |    2 
 src/hb-font.cc                                                                   |    4 
 src/hb-ft.cc                                                                     |    8 
 src/hb-open-type-private.hh                                                      |   10 
 src/hb-ot-cmap-table.hh                                                          |   23 +
 src/hb-ot-color-colr-table.hh                                                    |   10 
 src/hb-ot-color-cpal-table.hh                                                    |   18 -
 src/hb-ot-color-sbix-table.hh                                                    |    2 
 src/hb-ot-color-svg-table.hh                                                     |    6 
 src/hb-ot-font.cc                                                                |    6 
 src/hb-ot-glyf-table.hh                                                          |   18 +
 src/hb-ot-layout-common-private.hh                                               |    2 
 src/hb-ot-layout-gpos-table.hh                                                   |    2 
 src/hb-ot-os2-unicode-ranges.hh                                                  |    2 
 src/hb-ot-shape-complex-indic-machine.hh                                         |    2 
 src/hb-ot-shape-complex-indic-machine.rl                                         |    2 
 src/hb-ot-shape-complex-indic.cc                                                 |    3 
 src/hb-ot-shape-complex-khmer-machine.hh                                         |    2 
 src/hb-ot-shape-complex-khmer-machine.rl                                         |    2 
 src/hb-ot-shape-complex-use-machine.hh                                           |    2 
 src/hb-ot-shape-complex-use-machine.rl                                           |    2 
 src/hb-ot-shape-normalize.cc                                                     |    4 
 src/hb-set.cc                                                                    |    2 
 src/hb-unicode.cc                                                                |    2 
 src/main.cc                                                                      |   34 +-
 src/test-buffer-serialize.cc                                                     |   42 ---
 src/test-size-params.cc                                                          |   42 ---
 src/test-would-substitute.cc                                                     |   42 ---
 src/test.cc                                                                      |   42 ---
 test/api/fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf                                 |binary
 test/api/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a                      |binary
 test/api/hb-subset-test.h                                                        |   54 ----
 test/api/hb-test.h                                                               |   33 --
 test/api/test-subset-cmap.c                                                      |   23 +
 test/api/test-subset-glyf.c                                                      |   31 ++
 test/fuzzing/CMakeLists.txt                                                      |    7 
 test/fuzzing/Makefile.am                                                         |   16 +
 test/fuzzing/hb-subset-fuzzer.cc                                                 |   13 
 test/fuzzing/hb-subset-get-codepoints-fuzzer.cc                                  |   23 +
 test/fuzzing/run-subset-fuzzer-tests.py                                          |   19 +
 test/shaping/data/in-house/Makefile.sources                                      |    1 
 test/shaping/data/in-house/fonts/932ad5132c2761297c74e9976fe25b08e5ffa10b.ttf    |binary
 test/shaping/data/in-house/tests/indic-decompose.tests                           |    1 
 test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf    |binary
 test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf |binary
 test/subset/data/tests/full-font.tests                                           |    1 
 util/options.cc                                                                  |  110 +++-----
 util/options.hh                                                                  |    6 
 util/view-cairo.cc                                                               |    2 
 util/view-cairo.hh                                                               |    3 
 65 files changed, 468 insertions(+), 511 deletions(-)

New commits:
commit 9925030f19851957381b78c197e6f50c77fde756
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Apr 13 12:43:29 2018 +0430

    Don't decompose Bengali Rra and Rha
    
    Fixes #779 and follow up to b01d9b3d90e892341ee4463f2eda4600850b97d8

diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index fdc8966e..cd80da60 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -1470,6 +1470,9 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c,
   {
     /* Don't decompose these. */
     case 0x0931u  : return false; /* DEVANAGARI LETTER RRA */
+    // https://github.com/harfbuzz/harfbuzz/issues/779
+    case 0x09DCu  : return false; /* BENGALI LETTER RRA */
+    case 0x09DDu  : return false; /* BENGALI LETTER RHA */
     case 0x0B94u  : return false; /* TAMIL LETTER AU */
 
 
diff --git a/test/shaping/data/in-house/Makefile.sources b/test/shaping/data/in-house/Makefile.sources
index 1922fd4c..9a1434ec 100644
--- a/test/shaping/data/in-house/Makefile.sources
+++ b/test/shaping/data/in-house/Makefile.sources
@@ -16,6 +16,7 @@ TESTS = \
 	tests/hangul-jamo.tests \
 	tests/hyphens.tests \
 	tests/indic-consonant-with-stacker.tests \
+	tests/indic-decompose.tests \
 	tests/indic-init.tests \
 	tests/indic-joiner-candrabindu.tests \
 	tests/indic-joiners.tests \
diff --git a/test/shaping/data/in-house/fonts/932ad5132c2761297c74e9976fe25b08e5ffa10b.ttf b/test/shaping/data/in-house/fonts/932ad5132c2761297c74e9976fe25b08e5ffa10b.ttf
new file mode 100644
index 00000000..ef20bf80
Binary files /dev/null and b/test/shaping/data/in-house/fonts/932ad5132c2761297c74e9976fe25b08e5ffa10b.ttf differ
diff --git a/test/shaping/data/in-house/tests/indic-decompose.tests b/test/shaping/data/in-house/tests/indic-decompose.tests
new file mode 100644
index 00000000..ca887bea
--- /dev/null
+++ b/test/shaping/data/in-house/tests/indic-decompose.tests
@@ -0,0 +1 @@
+../fonts/932ad5132c2761297c74e9976fe25b08e5ffa10b.ttf:--font-funcs=ot:U+09DC,U+0020,U+09DD,U+0020,U+09A1,U+09BC,U+0020,U+09A2,U+09BC:[bn_rha=0+1024|space=1+1024|bn_yya=2+1024|space=3+1024|bn_dda=4+1024|bn_nukta=4+1024|space=6+1024|bn_ddha=7+1024|bn_nukta=7+1024]
commit 5ad87a93fefcb94ee5f28de8d75903b2550c8d94
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Wed Apr 25 16:44:04 2018 +0430

    Minor, improve file reading failing condition comment
    
    https://bugzilla.gnome.org/show_bug.cgi?id=659212 for more context

diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index d15a7cb3..710765d1 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -577,7 +577,8 @@ hb_blob_create_from_file (const char *file_name)
   struct stat st;
   if (unlikely (fstat (fd, &st) == -1)) goto fail;
 
-  // If the file size is 0 and isn't regular, give up
+  // If the file size is 0 and is a regular file, give up
+  // See https://github.com/GNOME/glib/blob/f9faac7/glib/gmappedfile.c#L139-L142
   if (unlikely (st.st_size == 0 && S_ISREG (st.st_mode))) goto fail;
 
   file->length = (unsigned long) st.st_size;
commit 2eaba80cbd3afb32363da93ebf6e60b11509d3f8
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Tue Apr 24 09:04:15 2018 +0430

    Minor, re-add unused mark to some of ragel defined state machines (#1005)

diff --git a/src/hb-ot-shape-complex-indic-machine.hh b/src/hb-ot-shape-complex-indic-machine.hh
index d0b00828..73f9d587 100644
--- a/src/hb-ot-shape-complex-indic-machine.hh
+++ b/src/hb-ot-shape-complex-indic-machine.hh
@@ -1129,7 +1129,7 @@ static const int indic_syllable_machine_en_main = 166;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts, te, act;
+  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl
index e50fe165..35e7ce90 100644
--- a/src/hb-ot-shape-complex-indic-machine.rl
+++ b/src/hb-ot-shape-complex-indic-machine.rl
@@ -104,7 +104,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts, te, act;
+  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
diff --git a/src/hb-ot-shape-complex-khmer-machine.hh b/src/hb-ot-shape-complex-khmer-machine.hh
index a5ed55f6..d0010215 100644
--- a/src/hb-ot-shape-complex-khmer-machine.hh
+++ b/src/hb-ot-shape-complex-khmer-machine.hh
@@ -173,7 +173,7 @@ static const int khmer_syllable_machine_en_main = 10;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts, te, act;
+  unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
diff --git a/src/hb-ot-shape-complex-khmer-machine.rl b/src/hb-ot-shape-complex-khmer-machine.rl
index bb535dad..54644d8a 100644
--- a/src/hb-ot-shape-complex-khmer-machine.rl
+++ b/src/hb-ot-shape-complex-khmer-machine.rl
@@ -86,7 +86,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts, te, act;
+  unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
diff --git a/src/hb-ot-shape-complex-myanmar-machine.hh b/src/hb-ot-shape-complex-myanmar-machine.hh
index 94fa7882..fb67dd42 100644
--- a/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -294,7 +294,7 @@ static const int myanmar_syllable_machine_en_main = 0;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts, te, act;
+  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
diff --git a/src/hb-ot-shape-complex-myanmar-machine.rl b/src/hb-ot-shape-complex-myanmar-machine.rl
index 860ac5f9..0cd84fa1 100644
--- a/src/hb-ot-shape-complex-myanmar-machine.rl
+++ b/src/hb-ot-shape-complex-myanmar-machine.rl
@@ -106,7 +106,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts, te, act;
+  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
diff --git a/src/hb-ot-shape-complex-use-machine.hh b/src/hb-ot-shape-complex-use-machine.hh
index 041450c9..0ec805af 100644
--- a/src/hb-ot-shape-complex-use-machine.hh
+++ b/src/hb-ot-shape-complex-use-machine.hh
@@ -331,7 +331,7 @@ static const int use_syllable_machine_en_main = 4;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts, te, act;
+  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl
index e5910a44..782a934a 100644
--- a/src/hb-ot-shape-complex-use-machine.rl
+++ b/src/hb-ot-shape-complex-use-machine.rl
@@ -153,7 +153,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts, te, act;
+  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
commit 48f0204cfea616a788d75c5065ad4999c7685513
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Tue Apr 24 08:11:13 2018 +0430

    Minor, re-add unused mark for two TRACE_ macros
    
    To revive Travis CI bot

diff --git a/src/hb-debug.hh b/src/hb-debug.hh
index cbb716a7..c244347b 100644
--- a/src/hb-debug.hh
+++ b/src/hb-debug.hh
@@ -357,7 +357,7 @@ struct hb_no_trace_t {
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 " ")
 #else
-#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace
+#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
 #endif
 
 #ifndef HB_DEBUG_COLLECT_GLYPHS
@@ -369,7 +369,7 @@ struct hb_no_trace_t {
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 " ")
 #else
-#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace
+#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
 #endif
 
 #ifndef HB_DEBUG_SANITIZE
commit 816b8169a90e0454b82a83719fc9ec1c83934d6f
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Apr 23 19:36:53 2018 +0430

    Resolve some of clang's double-promotion warnings

diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index d093c1c7..0617e23d 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -104,7 +104,7 @@ struct TrackData
     const TrackTableEntry *trackTableEntry = nullptr;
     for (unsigned int i = 0; i < sizes; ++i)
       // For now we only seek for track entries with zero tracking value
-      if (trackTable[i].get_track_value () == 0.)
+      if (trackTable[i].get_track_value () == 0.f)
         trackTableEntry = &trackTable[0];
 
     // We couldn't match any, exit
@@ -127,8 +127,8 @@ struct TrackData
     float s0 = size_table[size_index - 1].to_float ();
     float s1 = size_table[size_index].to_float ();
     float t = (csspx - s0) / (s1 - s0);
-    return t * trackTableEntry->get_value (base, size_index) +
-      (1.0 - t) * trackTableEntry->get_value (base, size_index - 1);
+    return (float) t * trackTableEntry->get_value (base, size_index) +
+	   ((float) 1.0 - t) * trackTableEntry->get_value (base, size_index - 1);
   }
 
   protected:
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 382fccb2..efbaa7ad 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -684,8 +684,8 @@ typedef HBUINT16 UFWORD;
 struct F2DOT14 : HBINT16
 {
   // 16384 means 1<<14
-  inline float to_float (void) const { return ((int32_t) v) / 16384.0; }
-  inline void set_float (float f) { v.set (round (f * 16384.0)); }
+  inline float to_float (void) const { return ((int32_t) v) / 16384.f; }
+  inline void set_float (float f) { v.set (round (f * 16384.f)); }
   public:
   DEFINE_SIZE_STATIC (2);
 };
@@ -694,8 +694,8 @@ struct F2DOT14 : HBINT16
 struct Fixed : HBINT32
 {
   // 65536 means 1<<16
-  inline float to_float (void) const { return ((int32_t) v) / 65536.0; }
-  inline void set_float (float f) { v.set (round (f * 65536.0)); }
+  inline float to_float (void) const { return ((int32_t) v) / 65536.f; }
+  inline void set_float (float f) { v.set (round (f * 65536.f)); }
   public:
   DEFINE_SIZE_STATIC (4);
 };
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 66df2a71..bd193f9d 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -1280,7 +1280,7 @@ struct VarRegionList
     {
       int coord = i < coord_len ? coords[i] : 0;
       float factor = axes[i].evaluate (coord);
-      if (factor == 0.)
+      if (factor == 0.f)
         return 0.;
       v *= factor;
     }
commit 24b8b9b227f53b4f67a713c994cec04a5f774634
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Apr 23 19:03:57 2018 +0430

    Resolve clang's used-but-marked-unused warnings

diff --git a/src/hb-debug.hh b/src/hb-debug.hh
index c244347b..cbb716a7 100644
--- a/src/hb-debug.hh
+++ b/src/hb-debug.hh
@@ -357,7 +357,7 @@ struct hb_no_trace_t {
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 " ")
 #else
-#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
+#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace
 #endif
 
 #ifndef HB_DEBUG_COLLECT_GLYPHS
@@ -369,7 +369,7 @@ struct hb_no_trace_t {
 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
 	 " ")
 #else
-#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
+#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace
 #endif
 
 #ifndef HB_DEBUG_SANITIZE
diff --git a/src/hb-font.cc b/src/hb-font.cc
index f3534b68..4d62b9e9 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -127,7 +127,7 @@ hb_font_get_variation_glyph_parent (hb_font_t *font,
 
 
 static hb_position_t
-hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_h_advance_nil (hb_font_t *font,
 				 void *font_data HB_UNUSED,
 				 hb_codepoint_t glyph,
 				 void *user_data HB_UNUSED)
@@ -144,7 +144,7 @@ hb_font_get_glyph_h_advance_parent (hb_font_t *font,
 }
 
 static hb_position_t
-hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
+hb_font_get_glyph_v_advance_nil (hb_font_t *font,
 				 void *font_data HB_UNUSED,
 				 hb_codepoint_t glyph,
 				 void *user_data HB_UNUSED)
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index aa6c1a10..69132386 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -210,7 +210,7 @@ hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
 }
 
 static hb_position_t
-hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
+hb_ft_get_glyph_h_advance (hb_font_t *font,
 			   void *font_data,
 			   hb_codepoint_t glyph,
 			   void *user_data HB_UNUSED)
@@ -228,7 +228,7 @@ hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED,
 }
 
 static hb_position_t
-hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
+hb_ft_get_glyph_v_advance (hb_font_t *font,
 			   void *font_data,
 			   hb_codepoint_t glyph,
 			   void *user_data HB_UNUSED)
@@ -248,7 +248,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
 }
 
 static hb_bool_t
-hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
+hb_ft_get_glyph_v_origin (hb_font_t *font,
 			  void *font_data,
 			  hb_codepoint_t glyph,
 			  hb_position_t *x,
@@ -292,7 +292,7 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
 }
 
 static hb_bool_t
-hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
+hb_ft_get_glyph_extents (hb_font_t *font,
 			 void *font_data,
 			 hb_codepoint_t glyph,
 			 hb_glyph_extents_t *extents,
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 1f2421b0..382fccb2 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -288,7 +288,7 @@ struct hb_sanitize_context_t :
     return likely (this->check_range (obj, obj->min_size));
   }
 
-  inline bool may_edit (const void *base HB_UNUSED, unsigned int len HB_UNUSED)
+  inline bool may_edit (const void *base, unsigned int len)
   {
     if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
       return false;
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 5e7a6da0..83102303 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -143,7 +143,7 @@ hb_ot_get_glyph_h_kerning (hb_font_t *font,
 }
 
 static hb_bool_t
-hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
+hb_ot_get_glyph_extents (hb_font_t *font,
 			 void *font_data,
 			 hb_codepoint_t glyph,
 			 hb_glyph_extents_t *extents,
@@ -184,7 +184,7 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
 }
 
 static hb_bool_t
-hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
+hb_ot_get_font_h_extents (hb_font_t *font,
 			  void *font_data,
 			  hb_font_extents_t *metrics,
 			  void *user_data HB_UNUSED)
@@ -198,7 +198,7 @@ hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
 }
 
 static hb_bool_t
-hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
+hb_ot_get_font_v_extents (hb_font_t *font,
 			  void *font_data,
 			  hb_font_extents_t *metrics,
 			  void *user_data HB_UNUSED)
diff --git a/src/hb-ot-shape-complex-indic-machine.hh b/src/hb-ot-shape-complex-indic-machine.hh
index f3cea227..d0b00828 100644
--- a/src/hb-ot-shape-complex-indic-machine.hh
+++ b/src/hb-ot-shape-complex-indic-machine.hh
@@ -1129,7 +1129,7 @@ static const int indic_syllable_machine_en_main = 166;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl
index 0ea91c0c..e50fe165 100644
--- a/src/hb-ot-shape-complex-indic-machine.rl
+++ b/src/hb-ot-shape-complex-indic-machine.rl
@@ -104,7 +104,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
diff --git a/src/hb-ot-shape-complex-khmer-machine.hh b/src/hb-ot-shape-complex-khmer-machine.hh
index 380705a5..a5ed55f6 100644
--- a/src/hb-ot-shape-complex-khmer-machine.hh
+++ b/src/hb-ot-shape-complex-khmer-machine.hh
@@ -173,7 +173,7 @@ static const int khmer_syllable_machine_en_main = 10;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
diff --git a/src/hb-ot-shape-complex-khmer-machine.rl b/src/hb-ot-shape-complex-khmer-machine.rl
index 8b00c37f..bb535dad 100644
--- a/src/hb-ot-shape-complex-khmer-machine.rl
+++ b/src/hb-ot-shape-complex-khmer-machine.rl
@@ -86,7 +86,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
diff --git a/src/hb-ot-shape-complex-myanmar-machine.hh b/src/hb-ot-shape-complex-myanmar-machine.hh
index fb67dd42..94fa7882 100644
--- a/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -294,7 +294,7 @@ static const int myanmar_syllable_machine_en_main = 0;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
diff --git a/src/hb-ot-shape-complex-myanmar-machine.rl b/src/hb-ot-shape-complex-myanmar-machine.rl
index 0cd84fa1..860ac5f9 100644
--- a/src/hb-ot-shape-complex-myanmar-machine.rl
+++ b/src/hb-ot-shape-complex-myanmar-machine.rl
@@ -106,7 +106,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
diff --git a/src/hb-ot-shape-complex-use-machine.hh b/src/hb-ot-shape-complex-use-machine.hh
index 0bf3ad30..041450c9 100644
--- a/src/hb-ot-shape-complex-use-machine.hh
+++ b/src/hb-ot-shape-complex-use-machine.hh
@@ -331,7 +331,7 @@ static const int use_syllable_machine_en_main = 4;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl
index 11fb4702..e5910a44 100644
--- a/src/hb-ot-shape-complex-use-machine.rl
+++ b/src/hb-ot-shape-complex-use-machine.rl
@@ -153,7 +153,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
diff --git a/src/hb-set.cc b/src/hb-set.cc
index 07cf9d09..af590ef3 100644
--- a/src/hb-set.cc
+++ b/src/hb-set.cc
@@ -150,7 +150,7 @@ hb_set_get_user_data (hb_set_t           *set,
  * Since: 0.9.2
  **/
 hb_bool_t
-hb_set_allocation_successful (const hb_set_t  *set HB_UNUSED)
+hb_set_allocation_successful (const hb_set_t  *set)
 {
   return !set->in_error;
 }
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index 726baeb0..2d16c2e3 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -64,7 +64,7 @@ hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
 
 static hb_codepoint_t
 hb_unicode_mirroring_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
-			  hb_codepoint_t      unicode   HB_UNUSED,
+			  hb_codepoint_t      unicode,
 			  void               *user_data HB_UNUSED)
 {
   return unicode;
commit eaf649450a29115ca0b2aac2921cc40c17aa55ac
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Apr 23 18:39:40 2018 +0430

    Resolve clang's conditional-uninitialize warnings

diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 62517077..bc8a5fd6 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -262,7 +262,7 @@ struct AnchorFormat2
     hb_font_t *font = c->font;
     unsigned int x_ppem = font->x_ppem;
     unsigned int y_ppem = font->y_ppem;
-    hb_position_t cx, cy;
+    hb_position_t cx = 0, cy = 0;
     hb_bool_t ret;
 
     ret = (x_ppem || y_ppem) &&
diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc
index 62cbb9de..eceea9e6 100644
--- a/src/hb-ot-shape-normalize.cc
+++ b/src/hb-ot-shape-normalize.cc
@@ -119,7 +119,7 @@ skip_char (hb_buffer_t *buffer)
 static inline unsigned int
 decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint_t ab)
 {
-  hb_codepoint_t a, b, a_glyph, b_glyph;
+  hb_codepoint_t a = 0, b = 0, a_glyph = 0, b_glyph = 0;
   hb_buffer_t * const buffer = c->buffer;
   hb_font_t * const font = c->font;
 
@@ -164,7 +164,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
 {
   hb_buffer_t * const buffer = c->buffer;
   hb_codepoint_t u = buffer->cur().codepoint;
-  hb_codepoint_t glyph;
+  hb_codepoint_t glyph = 0;
 
   if (shortest && c->font->get_nominal_glyph (u, &glyph))
   {
diff --git a/util/view-cairo.cc b/util/view-cairo.cc
index f4f2bc50..e8e334be 100644
--- a/util/view-cairo.cc
+++ b/util/view-cairo.cc
@@ -49,7 +49,7 @@ view_cairo_t::render (const font_options_t *font_opts)
   double leading = font_height + view_options.line_space;
 
   /* Calculate surface size. */
-  double w, h;
+  double w = 0, h = 0;
   (vertical ? w : h) = (int) lines->len * leading - view_options.line_space;
   (vertical ? h : w) = 0;
   for (unsigned int i = 0; i < lines->len; i++) {
commit 8b0d642e6610dd44f98a986580451eb562276897
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Apr 23 18:37:35 2018 +0430

    Resolve some of clang's zero-as-null-pointer-constant warnings

diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 7055e5f7..bb9b5ca2 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -210,7 +210,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
       return ct_font;
   }
 
-  CFURLRef original_url = NULL;
+  CFURLRef original_url = nullptr;
 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
   ATSFontRef atsFont;
   FSRef fsref;
@@ -240,7 +240,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
        * system locations that we cannot access from the sandboxed renderer
        * process in Blink. This can be detected by the new file URL location
        * that the newly found font points to. */
-      CFURLRef new_url = NULL;
+      CFURLRef new_url = nullptr;
 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
       atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
       status = ATSFontGetFileReference (atsFont, &fsref);
diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index e4138475..95868719 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -49,7 +49,7 @@ hb_bsearch_r (const void *key, const void *base,
     else
       return (void *) p;
   }
-  return NULL;
+  return nullptr;
 }
 
 
diff --git a/src/hb-ot-os2-unicode-ranges.hh b/src/hb-ot-os2-unicode-ranges.hh
index 2cf168f9..9b32cfab 100644
--- a/src/hb-ot-os2-unicode-ranges.hh
+++ b/src/hb-ot-os2-unicode-ranges.hh
@@ -237,7 +237,7 @@ hb_get_unicode_range_bit (hb_codepoint_t cp)
                                         sizeof (os2UnicodeRangesSorted) / sizeof(Range),
                                         sizeof(Range),
                                         _compare_range, nullptr);
-  if (range != NULL)
+  if (range != nullptr)
     return range->bit;
   return -1;
 }
commit 8100380d9e6fdd52eb7054f3300046028dcde8f9
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Sun Apr 22 10:58:37 2018 +0430

    Minor, fix calloc call order

diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 6ce3274b..d15a7cb3 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -572,7 +572,7 @@ hb_blob_create_from_file (const char *file_name)
   int fd = open (file_name, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
   if (unlikely (fd == -1)) return hb_blob_get_empty ();
 
-  hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (sizeof (hb_mapped_file_t), 1);
+  hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
 
   struct stat st;
   if (unlikely (fstat (fd, &st) == -1)) goto fail;
commit 2a4cdfad20fa8f0d2894383c2f10a6983f88b34b
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Apr 20 21:12:58 2018 +0430

    [aat/kerx] Minor (#1003)

diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 5004f27f..52637e6e 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -30,6 +30,7 @@
 
 #include "hb-open-type-private.hh"
 #include "hb-aat-layout-common-private.hh"
+#include "hb-aat-layout-ankr-table.hh"
 
 /*
  * kerx -- Extended Kerning
@@ -48,7 +49,7 @@ struct KerxFormat0Records
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   protected:
@@ -74,8 +75,8 @@ struct KerxSubTableFormat0
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  recordsZ.sanitize (c, nPairs));
+    return_trace (likely (c->check_struct (this) &&
+			  recordsZ.sanitize (c, nPairs)));
   }
 
   protected:
@@ -98,8 +99,8 @@ struct KerxSubTableFormat1
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  stateHeader.sanitize (c));
+    return_trace (likely (c->check_struct (this) &&
+			  stateHeader.sanitize (c)));
   }
 
   protected:
@@ -117,7 +118,8 @@ struct KerxClassTable
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
+    return_trace (likely (firstGlyph.sanitize (c) &&
+			  classes.sanitize (c)));
   }
 
   protected:
@@ -146,11 +148,11 @@ struct KerxSubTableFormat2
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  rowWidth.sanitize (c) &&
-		  leftClassTable.sanitize (c, this) &&
-		  rightClassTable.sanitize (c, this) &&
-		  array.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+			  rowWidth.sanitize (c) &&
+			  leftClassTable.sanitize (c, this) &&
+			  rightClassTable.sanitize (c, this) &&
+			  array.sanitize (c, this)));
   }
 
   protected:
@@ -173,11 +175,11 @@ struct KerxSubTableFormat4
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  rowWidth.sanitize (c) &&
-		  leftClassTable.sanitize (c, this) &&
-		  rightClassTable.sanitize (c, this) &&
-		  array.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+			  rowWidth.sanitize (c) &&
+			  leftClassTable.sanitize (c, this) &&
+			  rightClassTable.sanitize (c, this) &&
+			  array.sanitize (c, this)));
   }
 
   protected:
@@ -200,11 +202,11 @@ struct KerxSubTableFormat6
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  rowIndexTable.sanitize (c, this) &&
-		  columnIndexTable.sanitize (c, this) &&
-		  kerningArray.sanitize (c, this) &&
-		  kerningVector.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+			  rowIndexTable.sanitize (c, this) &&
+			  columnIndexTable.sanitize (c, this) &&
+			  kerningArray.sanitize (c, this) &&
+			  kerningVector.sanitize (c, this)));
   }
 
   protected:
@@ -276,7 +278,7 @@ struct SubtableGlyphCoverageArray
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   protected:
commit ce17340b23d96f543cd88e400e631bdb5656331c
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Fri Apr 20 10:29:06 2018 +0430

    Add hb_blob_create_from_file, a new API (#926)

diff --git a/TODO b/TODO
index 53ffbe9d..c6804d12 100644
--- a/TODO
+++ b/TODO
@@ -17,8 +17,6 @@ API additions
 
 - Language to/from script.
 
-- blob_from_file?
-
 - Add hb-cairo glue
 
 - Add sanitize API (and a cached version, that saves result on blob user-data)
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index 91faa0b7..73840391 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -8,6 +8,7 @@ HB_EXTERN
 <SECTION>
 <FILE>hb-blob</FILE>
 hb_blob_create
+hb_blob_create_from_file
 hb_blob_create_sub_blob
 hb_blob_copy_writable_or_fail
 hb_blob_destroy
diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc
index 16850d03..e173a5ee 100644
--- a/src/dump-emoji.cc
+++ b/src/dump-emoji.cc
@@ -219,38 +219,7 @@ int main (int argc, char **argv)
     exit (1);
   }
 
-  hb_blob_t *blob = nullptr;
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
   hb_face_t *face = hb_face_create (blob, 0);
   hb_font_t *font = hb_font_create (face);
 
diff --git a/src/dump-fon.cc b/src/dump-fon.cc
index 4d923563..1d18983c 100644
--- a/src/dump-fon.cc
+++ b/src/dump-fon.cc
@@ -538,22 +538,13 @@ struct LE_IMAGE_DOS_HEADER {
 };
 
 int main (int argc, char** argv) {
-  FILE *f = fopen (argv[1], "rb");
-  fseek (f, 0, SEEK_END);
-  unsigned int len = ftell (f);
-  rewind (f);
-  const char *font_data = (const char *) malloc (len);
-  len = fread ((char *) font_data, 1, len, f);
-
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
 
   OT::Sanitizer<LE_IMAGE_DOS_HEADER> sanitizer;
-  hb_blob_t *blob = hb_blob_create (font_data, len, HB_MEMORY_MODE_WRITABLE,
-				    (void *) font_data, free);
   hb_blob_t *font_blob = sanitizer.sanitize (blob);
   const LE_IMAGE_DOS_HEADER* dos_header =
     OT::Sanitizer<LE_IMAGE_DOS_HEADER>::lock_instance (font_blob);
 
-
   const NE_RESOURCE_TABLE &rtable = dos_header->get_os2_header ().get_resource_table ();
   int shift = rtable.get_shift_value ();
   const NE_TYPEINFO& entry = rtable.get_fonts_entry ();
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index b5291f65..6ce3274b 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -43,6 +43,10 @@
 
 #include <stdio.h>
 #include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 
 struct hb_blob_t {
@@ -273,7 +277,7 @@ hb_blob_destroy (hb_blob_t *blob)
  * @destroy: callback to call when @data is not needed anymore.
  * @replace: whether to replace an existing data with the same key.
  *
- * Return value: 
+ * Return value:
  *
  * Since: 0.9.2
  **/
@@ -292,9 +296,9 @@ hb_blob_set_user_data (hb_blob_t          *blob,
  * @blob: a blob.
  * @key: key for data to get.
  *
- * 
  *
- * Return value: (transfer none): 
+ *
+ * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
@@ -310,7 +314,7 @@ hb_blob_get_user_data (hb_blob_t          *blob,
  * hb_blob_make_immutable:
  * @blob: a blob.
  *
- * 
+ *
  *
  * Since: 0.9.2
  **/
@@ -327,7 +331,7 @@ hb_blob_make_immutable (hb_blob_t *blob)
  * hb_blob_is_immutable:
  * @blob: a blob.
  *
- * 
+ *
  *
  * Return value: TODO
  *
@@ -344,7 +348,7 @@ hb_blob_is_immutable (hb_blob_t *blob)
  * hb_blob_get_length:
  * @blob: a blob.
  *
- * 
+ *
  *
  * Return value: the length of blob data in bytes.
  *
@@ -361,9 +365,9 @@ hb_blob_get_length (hb_blob_t *blob)
  * @blob: a blob.
  * @length: (out):
  *
- * 
  *
- * Returns: (transfer none) (array length=length): 
+ *
+ * Returns: (transfer none) (array length=length):
  *
  * Since: 0.9.2
  **/
@@ -502,3 +506,114 @@ _try_writable (hb_blob_t *blob)
 
   return true;
 }
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#include <windows.h>
+#include <io.h>
+
+#undef fstat
+#define fstat(a,b) _fstati64(a,b)
+#undef stat
+#define stat _stati64
+
+#ifndef S_ISREG
+# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
+#endif
+#endif // defined(_WIN32) || defined(__CYGWIN__)
+
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#ifndef MAP_FAILED
+# define MAP_FAILED ((void *) -1)
+#endif
+
+struct hb_mapped_file_t
+{
+  char *contents;
+  unsigned long length;
+#if defined(_WIN32) || defined(__CYGWIN__)
+  HANDLE mapping;
+#endif
+};
+
+static void
+_hb_mapped_file_destroy (hb_mapped_file_t *file)
+{
+#ifdef HAVE_MMAP
+  munmap (file->contents, file->length);
+#elif defined(_WIN32) || defined(__CYGWIN__)
+  UnmapViewOfFile (file->contents);
+  CloseHandle (file->mapping);
+#else
+  free (file->contents);
+#endif
+
+  free (file);
+}
+
+/**
+ * hb_blob_create_from_file:
+ * @file_name: font filename.
+ *
+ * Returns: A hb_blob_t pointer with the content of the file
+ *
+ * Since: REPLACEME
+ **/
+hb_blob_t *
+hb_blob_create_from_file (const char *file_name)
+{
+  // Adopted from glib's gmappedfile.c with Matthias Clasen and
+  // Allison Lortie permission but changed to suit our need.
+  bool writable = false;
+  hb_memory_mode_t mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
+
+  int fd = open (file_name, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
+  if (unlikely (fd == -1)) return hb_blob_get_empty ();
+
+  hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (sizeof (hb_mapped_file_t), 1);
+
+  struct stat st;
+  if (unlikely (fstat (fd, &st) == -1)) goto fail;
+
+  // If the file size is 0 and isn't regular, give up
+  if (unlikely (st.st_size == 0 && S_ISREG (st.st_mode))) goto fail;
+
+  file->length = (unsigned long) st.st_size;
+
+#ifdef HAVE_MMAP
+  file->contents = (char *) mmap (nullptr, file->length,
+				  writable ? PROT_READ|PROT_WRITE : PROT_READ,
+				  MAP_PRIVATE, fd, 0);
+  if (unlikely (file->contents == MAP_FAILED)) goto fail;
+#elif defined(_WIN32) || defined(__CYGWIN__)
+  file->mapping = CreateFileMapping ((HANDLE) _get_osfhandle (fd), nullptr,
+				     writable ? PAGE_WRITECOPY : PAGE_READONLY,
+				     0, 0, nullptr);
+  if (unlikely (file->mapping == nullptr)) goto fail;
+
+  file->contents = (char *) MapViewOfFile (file->mapping,
+					   writable ? FILE_MAP_COPY : FILE_MAP_READ,
+					   0, 0, 0);
+  if (unlikely (file->contents == nullptr))
+  {
+    CloseHandle (file->mapping);
+    goto fail;
+  }
+#else
+  file->contents = (char *) malloc (file->length);
+  if (unlikely (!file->contents)) goto fail;
+  read (fd, file->contents, file->length);
+  mm = HB_MEMORY_MODE_WRITABLE;
+#endif
+
+  close (fd);
+  return hb_blob_create (file->contents, file->length, mm, (void *) file,
+			 (hb_destroy_func_t) _hb_mapped_file_destroy);
+
+fail:
+  close (fd);
+  free (file);
+  return hb_blob_get_empty ();
+}
diff --git a/src/hb-blob.h b/src/hb-blob.h
index fd561f73..d1d9134a 100644
--- a/src/hb-blob.h
+++ b/src/hb-blob.h
@@ -123,6 +123,8 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length);
 HB_EXTERN char *
 hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);
 
+HB_EXTERN hb_blob_t *
+hb_blob_create_from_file (const char *file_name);
 
 HB_END_DECLS
 
diff --git a/src/main.cc b/src/main.cc
index 9423a728..935fa392 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -49,32 +49,12 @@ main (int argc, char **argv)
     exit (1);
   }
 
-  const char *font_data = nullptr;
-  int len = 0;
-  hb_destroy_func_t destroy;
-  hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-  GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-  font_data = g_mapped_file_get_contents (mf);
-  len = g_mapped_file_get_length (mf);
-  destroy = (hb_destroy_func_t) g_mapped_file_unref;
-  mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-  FILE *f = fopen (argv[1], "rb");
-  fseek (f, 0, SEEK_END);
-  len = ftell (f);
-  fseek (f, 0, SEEK_SET);
-  font_data = (const char *) malloc (len);
-  len = fread ((char *) font_data, 1, len, f);
-  destroy = free;
-  mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
+  unsigned int len;
+  const char *font_data = hb_blob_get_data (blob, &len);
   printf ("Opened font file %s: %d bytes long\n", argv[1], len);
 
   Sanitizer<OpenTypeFontFile> sanitizer;
-  hb_blob_t *blob = hb_blob_create (font_data, len, mm, (void *) font_data, destroy);
   hb_blob_t *font_blob = sanitizer.sanitize (blob);
   const OpenTypeFontFile* sanitized = Sanitizer<OpenTypeFontFile>::lock_instance (font_blob);
   if (sanitized == &Null (OpenTypeFontFile))
diff --git a/src/test-buffer-serialize.cc b/src/test-buffer-serialize.cc
index 636b0037..39eb13da 100644
--- a/src/test-buffer-serialize.cc
+++ b/src/test-buffer-serialize.cc
@@ -32,57 +32,17 @@
 #include "hb-ft.h"
 #endif
 
-#ifdef HAVE_GLIB
-# include <glib.h>
-# if !GLIB_CHECK_VERSION (2, 22, 0)
-#  define g_mapped_file_unref g_mapped_file_free
-# endif
-#endif
-#include <stdlib.h>
 #include <stdio.h>
 
 int
 main (int argc, char **argv)
 {
-  hb_blob_t *blob = nullptr;
-
   if (argc != 2) {
     fprintf (stderr, "usage: %s font-file\n", argv[0]);
     exit (1);
   }
 
-  /* Create the blob */
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_blob_destroy (blob);
   blob = nullptr;
diff --git a/src/test-size-params.cc b/src/test-size-params.cc
index 9741b87e..3c43852b 100644
--- a/src/test-size-params.cc
+++ b/src/test-size-params.cc
@@ -29,58 +29,18 @@
 #include "hb.h"
 #include "hb-ot.h"
 
-#ifdef HAVE_GLIB
-# include <glib.h>
-# if !GLIB_CHECK_VERSION (2, 22, 0)
-#  define g_mapped_file_unref g_mapped_file_free
-# endif
-#endif
-#include <stdlib.h>
 #include <stdio.h>
 
 int
 main (int argc, char **argv)
 {
-  hb_blob_t *blob = nullptr;
-
   if (argc != 2) {
     fprintf (stderr, "usage: %s font-file\n", argv[0]);
     exit (1);
   }
 
-  /* Create the blob */
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
   /* Create the face */
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_blob_destroy (blob);
   blob = nullptr;
diff --git a/src/test-would-substitute.cc b/src/test-would-substitute.cc
index efebf2d0..1836d720 100644
--- a/src/test-would-substitute.cc
+++ b/src/test-would-substitute.cc
@@ -29,13 +29,6 @@
 #include "hb.h"
 #include "hb-ot.h"
 
-#ifdef HAVE_GLIB
-# include <glib.h>
-# if !GLIB_CHECK_VERSION (2, 22, 0)
-#  define g_mapped_file_unref g_mapped_file_free
-# endif
-#endif
-#include <stdlib.h>
 #include <stdio.h>
 
 #ifdef HAVE_FREETYPE
@@ -45,46 +38,13 @@
 int
 main (int argc, char **argv)
 {
-  hb_blob_t *blob = nullptr;
-
   if (argc != 4 && argc != 5) {
     fprintf (stderr, "usage: %s font-file lookup-index first-glyph [second-glyph]\n", argv[0]);
     exit (1);
   }
 
-  /* Create the blob */
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
   /* Create the face */
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
   hb_blob_destroy (blob);
   blob = nullptr;
diff --git a/src/test.cc b/src/test.cc
index 9592b379..cf59e00a 100644
--- a/src/test.cc
+++ b/src/test.cc
@@ -28,13 +28,6 @@
 
 #include "hb.h"
 
-#ifdef HAVE_GLIB
-# include <glib.h>
-# if !GLIB_CHECK_VERSION (2, 22, 0)
-#  define g_mapped_file_unref g_mapped_file_free
-# endif
-#endif
-#include <stdlib.h>
 #include <stdio.h>
 
 #ifdef HAVE_FREETYPE
@@ -44,45 +37,12 @@
 int
 main (int argc, char **argv)
 {
-  hb_blob_t *blob = nullptr;
-
   if (argc != 2) {
     fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
     exit (1);
   }
 
-  /* Create the blob */
-  {
-    const char *font_data;
-    unsigned int len;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-#ifdef HAVE_GLIB
-    GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
-    font_data = g_mapped_file_get_contents (mf);
-    len = g_mapped_file_get_length (mf);
-    destroy = (hb_destroy_func_t) g_mapped_file_unref;
-    user_data = (void *) mf;
-    mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-#else
-    FILE *f = fopen (argv[1], "rb");
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    fseek (f, 0, SEEK_SET);
-    font_data = (const char *) malloc (len);
-    if (!font_data) len = 0;
-    len = fread ((char *) font_data, 1, len, f);
-    destroy = free;
-    user_data = (void *) font_data;
-    fclose (f);
-    mm = HB_MEMORY_MODE_WRITABLE;
-#endif
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
-  }
-
+  hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
   printf ("Opened font file %s: %u bytes long\n", argv[1], hb_blob_get_length (blob));
 
   /* Create the face */
diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h
index 49c3fddb..c34f394b 100644
--- a/test/api/hb-subset-test.h
+++ b/test/api/hb-subset-test.h
@@ -47,64 +47,16 @@ typedef short bool;
 
 HB_BEGIN_DECLS
 
-static inline char *
-hb_subset_test_read_file (const char *path,
-                          size_t     *length /* OUT */)
-{
-  FILE *fp = fopen (path, "rb");
-
-  long file_length = 0;
-  char *buffer = NULL;
-  if (fp && fseek (fp, 0, SEEK_END) == 0)
-  {
-    file_length = ftell(fp);
-    rewind (fp);
-  }
-
-  if (file_length > 0)
-  {
-    buffer = (char *) calloc (file_length + 1, sizeof (char));
-    if (buffer && fread (buffer, 1, file_length, fp) == (size_t) file_length)
-    {
-      *length = file_length;
-    }
-    else
-    {
-      free (buffer);
-      buffer = NULL;
-    }
-  }
-
-  if (fp)
-    fclose(fp);
-
-  return buffer;
-}
-
 static inline hb_face_t *
 hb_subset_test_open_font (const char *font_path)
 {
 #if GLIB_CHECK_VERSION(2,37,2)
-  gchar* path = g_test_build_filename(G_TEST_DIST, font_path, NULL);
+  char* path = g_test_build_filename(G_TEST_DIST, font_path, NULL);
 #else
-  gchar* path = g_strdup(font_path);
+  char* path = g_strdup(font_path);
 #endif
 
-  size_t length;
-  char *font_data = hb_subset_test_read_file(path, &length);
-
-  if (font_data != NULL) {
-    hb_blob_t *blob = hb_blob_create (font_data,
-                                      length,
-                                      HB_MEMORY_MODE_READONLY,
-                                      font_data,
-                                      free);
-    hb_face_t *face = hb_face_create (blob, 0);
-    hb_blob_destroy (blob);
-    return face;
-  }
-  g_assert (false);
-  return NULL; /* Shut up, compiler! */
+  return hb_face_create (hb_blob_create_from_file (path), 0);
 }
 
 static inline hb_subset_input_t *
diff --git a/test/api/hb-test.h b/test/api/hb-test.h
index c851f809..307845f6 100644
--- a/test/api/hb-test.h
+++ b/test/api/hb-test.h
@@ -87,39 +87,6 @@ hb_test_run (void)
   return g_test_run ();
 }
 
-
-#if 0
-/* Helpers for loading test fonts */
-static inline hb_face_t *
-hb_test_load_face (const char *path)
-{
-  const char *font_data = NULL;
-  unsigned int len = 0;
-  hb_blob_t *blob = NULL;
-  hb_face_t *face = NULL;
-
-  FILE *f = fopen (path, "rb");
-  if (!f) {
-    perror (path);
-    exit (1);
-  }
-
-  fseek (f, 0, SEEK_END);
-  len = ftell (f);
-  fseek (f, 0, SEEK_SET);
-  font_data = (const char *) malloc (len);
-  if (!font_data) len = 0;
-  len = fread ((char *) font_data, 1, len, f);
-  fclose (f);
-
-  blob = hb_blob_create (font_data, len, HB_MEMORY_MODE_READONLY, 0, free);
-  face = hb_face_create (blob, 0 /* first face */);
-  hb_blob_destroy (blob);
-  return face;
-}
-#endif
-
-
 /* Bugzilla helpers */
 
 static inline void
diff --git a/util/options.cc b/util/options.cc
index aad843c2..24dc41f2 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -65,8 +65,6 @@ fail (hb_bool_t suggest_help, const char *format, ...)
 }
 
 
-hb_bool_t debug = false;
-
 static gchar *
 shapers_to_string (void)
 {
@@ -107,7 +105,6 @@ option_parser_t::add_main_options (void)
   {
     {"version",		0, G_OPTION_FLAG_NO_ARG,
 			      G_OPTION_ARG_CALLBACK,	(gpointer) &show_version,	"Show version numbers",			nullptr},
-    {"debug",		0, 0, G_OPTION_ARG_NONE,	&debug,				"Free all resources before exit",	nullptr},
     {nullptr}
   };
   g_option_context_add_main_entries (context, entries, nullptr);
@@ -649,74 +646,29 @@ font_options_t::get_font (void) const
   hb_blob_t *blob = nullptr;
 
   /* Create the blob */
-  {
-    char *font_data;
-    unsigned int len = 0;
-    hb_destroy_func_t destroy;
-    void *user_data;
-    hb_memory_mode_t mm;
-
-    /* This is a hell of a lot of code for just reading a file! */
-    if (!font_file)
-      fail (true, "No font file set");
-
-    if (0 == strcmp (font_file, "-")) {
-      /* read it */
-      GString *gs = g_string_new (nullptr);
-      char buf[BUFSIZ];
+  if (!font_file)
+    fail (true, "No font file set");
+
+  if (0 == strcmp (font_file, "-")) {
+    /* read it */
+    GString *gs = g_string_new (nullptr);
+    char buf[BUFSIZ];
 #if defined(_WIN32) || defined(__CYGWIN__)
-      setmode (fileno (stdin), O_BINARY);
+    setmode (fileno (stdin), O_BINARY);
 #endif
-      while (!feof (stdin)) {
-	size_t ret = fread (buf, 1, sizeof (buf), stdin);
-	if (ferror (stdin))
-	  fail (false, "Failed reading font from standard input: %s",
-		strerror (errno));
-	g_string_append_len (gs, buf, ret);
-      }
-      len = gs->len;
-      font_data = g_string_free (gs, false);
-      user_data = font_data;
-      destroy = (hb_destroy_func_t) g_free;
-      mm = HB_MEMORY_MODE_WRITABLE;
-    } else {
-      GError *error = nullptr;
-      GMappedFile *mf = g_mapped_file_new (font_file, false, &error);
-      if (mf) {
-	font_data = g_mapped_file_get_contents (mf);
-	len = g_mapped_file_get_length (mf);
-	if (len) {
-	  destroy = (hb_destroy_func_t) g_mapped_file_unref;
-	  user_data = (void *) mf;
-	  mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
-	} else
-	  g_mapped_file_unref (mf);
-      } else {
-	fail (false, "%s", error->message);
-	//g_error_free (error);
-      }
-      if (!len) {
-	/* GMappedFile is buggy, it doesn't fail if file isn't regular.
-	 * Try reading.
-	 * https://bugzilla.gnome.org/show_bug.cgi?id=659212 */
-        GError *error = nullptr;
-	gsize l;
-	if (g_file_get_contents (font_file, &font_data, &l, &error)) {
-	  len = l;
-	  destroy = (hb_destroy_func_t) g_free;
-	  user_data = (void *) font_data;
-	  mm = HB_MEMORY_MODE_WRITABLE;
-	} else {
-	  fail (false, "%s", error->message);
-	  //g_error_free (error);
-	}
-      }
+    while (!feof (stdin)) {
+      size_t ret = fread (buf, 1, sizeof (buf), stdin);
+      if (ferror (stdin))
+	fail (false, "Failed reading font from standard input: %s",
+	      strerror (errno));
+      g_string_append_len (gs, buf, ret);
     }
-
-    if (debug)
-      mm = HB_MEMORY_MODE_DUPLICATE;
-
-    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
+    char *font_data = g_string_free (gs, false);
+    blob = hb_blob_create (font_data, gs->len,
+			   HB_MEMORY_MODE_WRITABLE, font_data,
+			   (hb_destroy_func_t) g_free);
+  } else {
+    blob = hb_blob_create_from_file (font_file);
   }
 
   /* Create the face */
diff --git a/util/options.hh b/util/options.hh
index 467350a9..8dfc8420 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -52,14 +52,8 @@
 #include <glib.h>
 #include <glib/gprintf.h>
 
-#if !GLIB_CHECK_VERSION (2, 22, 0)
-# define g_mapped_file_unref g_mapped_file_free
-#endif
-
 void fail (hb_bool_t suggest_help, const char *format, ...) G_GNUC_NORETURN G_GNUC_PRINTF (2, 3);
 
-extern hb_bool_t debug;
-
 struct option_group_t
 {
   virtual void add_options (struct option_parser_t *parser) = 0;
diff --git a/util/view-cairo.hh b/util/view-cairo.hh
index d28c3cd1..00df68c2 100644
--- a/util/view-cairo.hh
+++ b/util/view-cairo.hh
@@ -40,8 +40,7 @@ struct view_cairo_t
 		 direction (HB_DIRECTION_INVALID),
 		 lines (0), scale_bits (0) {}
   ~view_cairo_t (void) {
-    if (debug)
-      cairo_debug_reset_static_data ();
+    cairo_debug_reset_static_data ();
   }
 
   void init (hb_buffer_t *buffer, const font_options_t *font_opts)
commit 4fa1c6705a1bc5299adb5a848ceaf6ac8f33c0ba
Author: Garret Rieger <grieger at google.com>
Date:   Thu Apr 19 15:30:35 2018 -0700

    [subset] Check instruction offsets in glyph to ensure they are in bounds.

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 3e8b5eb4..85cb3a37 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -433,9 +433,23 @@ struct glyf
       else
       {
         unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
+	if (unlikely (instruction_length_offset + 2 > end_offset))
+	{
+	  DEBUG_MSG(SUBSET, nullptr, "Glyph size is too short, missing field instructionLength.");
+	  return false;
+	}
+
         const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
-        *instruction_start = instruction_length_offset + 2;
-        *instruction_end = *instruction_start + (uint16_t) instruction_length;
+	unsigned int start = instruction_length_offset + 2;
+	unsigned int end = start + (uint16_t) instruction_length;
+	if (unlikely (end > end_offset)) // Out of bounds of the current glyph
+	{
+	  DEBUG_MSG(SUBSET, nullptr, "The instructions array overruns the glyph's boundaries.");
+	  return false;
+	}
+
+	*instruction_start = start;
+        *instruction_end = end;
       }
       return true;
     }
diff --git a/test/api/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a b/test/api/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a
new file mode 100644
index 00000000..1af243eb
Binary files /dev/null and b/test/api/fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a differ
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
index e72086a3..4ea2d891 100644
--- a/test/api/test-subset-glyf.c
+++ b/test/api/test-subset-glyf.c
@@ -171,6 +171,36 @@ test_subset_glyf_strip_hints_composite (void)
   hb_face_destroy (face_components);
 }
 
+static void
+test_subset_glyf_strip_hints_invalid (void)
+{
+  hb_face_t *face = hb_subset_test_open_font ("fonts/oom-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
+
+  hb_set_t *codepoints = hb_set_create();
+  const hb_codepoint_t text[] =
+      {
+        'A', 'B', 'C', 'D', 'E', 'X', 'Y', 'Z', '1', '2',
+        '3', '@', '_', '%', '&', ')', '*', '$', '!'
+      };
+  int i;
+  for (i = 0; i < sizeof (text) / sizeof (hb_codepoint_t); i++)
+  {
+    hb_set_add (codepoints, text[i]);
+    // hb_set_add (codepoints_drop_hints, text[i]);
+  }
+
+  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  *hb_subset_input_drop_hints(input) = true;
+  hb_set_destroy (codepoints);
+
+  hb_face_t *face_subset = hb_subset_test_create_subset (face, input);
+  g_assert (face_subset);
+  g_assert (face_subset == hb_face_get_empty ());
+
+  hb_face_destroy (face_subset);
+  hb_face_destroy (face);
+}
+
 // TODO(grieger): test for long loca generation.
 
 int
@@ -182,6 +212,7 @@ main (int argc, char **argv)
   hb_test_add (test_subset_glyf);
   hb_test_add (test_subset_glyf_strip_hints_simple);
   hb_test_add (test_subset_glyf_strip_hints_composite);
+  hb_test_add (test_subset_glyf_strip_hints_invalid);
   hb_test_add (test_subset_glyf_with_components);
 
   return hb_test_run();
commit 3c97614598ecd0bbccb2c90a8e0e99f010952b76
Author: Garret Rieger <grieger at google.com>
Date:   Thu Apr 19 13:39:57 2018 -0700

    [subset] In subset fuzzer run through drop hints and keep hints pathways.

diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index dfa83613..8bf6b4fa 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -12,10 +12,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t 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_subset_input_drop_hints(input) = false;
   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
 
+  hb_subset_input_t *input_drop_hints = hb_subset_input_create_or_fail ();
+  *hb_subset_input_drop_hints(input_drop_hints) = true;
+  hb_set_t *codepoints_drop_hints = hb_subset_input_unicode_set (input);
+
   const hb_codepoint_t text[] =
       {
         'A', 'B', 'C', 'D', 'E', 'X', 'Y', 'Z', '1', '2',
@@ -24,12 +29,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
   for (int i = 0; i < sizeof (text) / sizeof (hb_codepoint_t); i++)
   {
     hb_set_add (codepoints, text[i]);
+    hb_set_add (codepoints_drop_hints, text[i]);
   }
 
   hb_face_t *result = hb_subset (face, profile, input);
+  hb_face_destroy (result);
 
+  result = hb_subset (face, profile, input_drop_hints);
   hb_face_destroy (result);
+
   hb_subset_input_destroy (input);
+  hb_subset_input_destroy (input_drop_hints);
   hb_subset_profile_destroy (profile);
   hb_face_destroy (face);
   hb_blob_destroy (blob);
commit 6fdeeb2ae3059ac1bc5ff99fd1655b4e94576151
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Thu Apr 19 23:41:37 2018 +0300

    [util] Check all specified shapers are known (#993)
    
    A bit brute force and requires all shapers to be known, not just one.
    
    Fixes https://github.com/harfbuzz/harfbuzz/issues/956

diff --git a/util/options.cc b/util/options.cc
index c625d657..aad843c2 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -192,11 +192,29 @@ static gboolean
 parse_shapers (const char *name G_GNUC_UNUSED,
 	       const char *arg,
 	       gpointer    data,
-	       GError    **error G_GNUC_UNUSED)
+	       GError    **error)
 {
   shape_options_t *shape_opts = (shape_options_t *) data;
+  char **shapers = g_strsplit (arg, ",", 0);
+
+  for (char **shaper = shapers; *shaper; shaper++) {
+    bool found = false;
+    for (const char **hb_shaper = hb_shape_list_shapers (); *hb_shaper; hb_shaper++) {
+      if (strcmp (*shaper, *hb_shaper) == 0) {
+        found = true;
+        break;
+      }
+    }
+    if (!found) {
+      g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+		   "Unknown or unsupported shaper: %s", *shaper);
+      g_strfreev (shapers);
+      return false;
+    }
+  }
+
   g_strfreev (shape_opts->shapers);
-  shape_opts->shapers = g_strsplit (arg, ",", 0);
+  shape_opts->shapers = shapers;
   return true;
 }
 
commit 535fb23c0211c733d59f72c3431643d89dc16d16
Author: Garret Rieger <grieger at google.com>
Date:   Wed Apr 18 17:37:39 2018 -0700

    [subset] Add integration tests for cmap breakge.

diff --git a/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf b/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf
new file mode 100644
index 00000000..2ff53536
Binary files /dev/null and b/test/subset/data/expected/full-font/Roboto-Regular.default.D7,D8,D9,DA,DE.ttf differ
diff --git a/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf
new file mode 100644
index 00000000..895c6e6b
Binary files /dev/null and b/test/subset/data/expected/full-font/Roboto-Regular.drop-hints.D7,D8,D9,DA,DE.ttf differ
diff --git a/test/subset/data/tests/full-font.tests b/test/subset/data/tests/full-font.tests
index f0a262bf..ff195cea 100644
--- a/test/subset/data/tests/full-font.tests
+++ b/test/subset/data/tests/full-font.tests
@@ -8,4 +8,5 @@ drop-hints.txt
 SUBSETS:
 abc
 Ǽ!A bc
+×ØÙÚÞ
 
commit e29c8e33f3debf721e18306b896df7a3233386ac
Author: Garret Rieger <grieger at google.com>
Date:   Wed Apr 18 17:32:43 2018 -0700

    [subset] Add a test for previous cmap breakage.

diff --git a/test/api/fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf b/test/api/fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf
new file mode 100644
index 00000000..38799ccb
Binary files /dev/null and b/test/api/fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf differ
diff --git a/test/api/test-subset-cmap.c b/test/api/test-subset-cmap.c
index 618b7259..52548742 100644
--- a/test/api/test-subset-cmap.c
+++ b/test/api/test-subset-cmap.c
@@ -50,6 +50,28 @@ test_subset_cmap (void)
 }
 
 static void
+test_subset_cmap_non_consecutive_glyphs (void)
+{
+  hb_face_t *face = hb_subset_test_open_font ("fonts/Roboto-Regular.D7,D8,D9,DA,DE.ttf");
+
+  hb_set_t *codepoints = hb_set_create ();
+  hb_face_t *face_subset;
+  hb_set_add (codepoints, 0xD7);
+  hb_set_add (codepoints, 0xD8);
+  hb_set_add (codepoints, 0xD9);
+  hb_set_add (codepoints, 0xDA);
+  hb_set_add (codepoints, 0xDE);
+
+  face_subset = hb_subset_test_create_subset (face, hb_subset_test_create_input (codepoints));
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face, face_subset, HB_TAG ('c','m','a','p'));
+
+  hb_face_destroy (face_subset);
+  hb_face_destroy (face);
+}
+
+static void
 test_subset_cmap_noop (void)
 {
   hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.cmap-format12-only.ttf");
@@ -77,6 +99,7 @@ main (int argc, char **argv)
 
   hb_test_add (test_subset_cmap);
   hb_test_add (test_subset_cmap_noop);
+  hb_test_add (test_subset_cmap_non_consecutive_glyphs);
 
   return hb_test_run();
 }
commit 5e318e09ba590eef7b7ec047d7857f7f1eb7d787
Author: Garret Rieger <grieger at google.com>
Date:   Wed Apr 18 17:13:37 2018 -0700

    [subset] Fix broken cmap creation.
    It was ignoring the restriction that gids must be consecutive to be placed into a single group.

diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 5e71eaba..7eb706af 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -539,6 +539,14 @@ struct cmap
 		  encodingRecord.sanitize (c, this));
   }
 
+  static inline bool _is_gid_consecutive (CmapSubtableLongGroup *group,
+					  hb_codepoint_t cp,
+					  hb_codepoint_t new_gid)
+  {
+    return (cp - 1 == group->endCharCode) &&
+	new_gid == group->glyphID + (cp - group->startCharCode);
+  }
+
   inline bool populate_groups (hb_subset_plan_t *plan,
 			       hb_prealloced_array_t<CmapSubtableLongGroup> *groups) const
   {
@@ -546,17 +554,18 @@ struct cmap
     for (unsigned int i = 0; i < plan->codepoints.len; i++) {
 
       hb_codepoint_t cp = plan->codepoints[i];
-      if (!group || cp - 1 != group->endCharCode)
+      hb_codepoint_t new_gid;
+      if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid)))
+      {
+	DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
+	return false;
+      }
+
+      if (!group || !_is_gid_consecutive (group, cp, new_gid))
       {
         group = groups->push ();
         group->startCharCode.set (cp);
         group->endCharCode.set (cp);
-        hb_codepoint_t new_gid;
-        if (unlikely (!hb_subset_plan_new_gid_for_codepoint (plan, cp, &new_gid)))
-        {
-          DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
-          return false;
-        }
         group->glyphID.set (new_gid);
       } else
       {
commit a47070cd40cee51fe792cb838ff9f21e0ea482c6
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Wed Apr 18 12:09:37 2018 +0430

    Minor, annotate the added tables with likely/unlikely (#997)

diff --git a/src/hb-aat-fmtx-table.hh b/src/hb-aat-fmtx-table.hh
index a9185c37..aa82c88c 100644
--- a/src/hb-aat-fmtx-table.hh
+++ b/src/hb-aat-fmtx-table.hh
@@ -44,7 +44,7 @@ struct fmtx
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   FixedVersion<>version;		/* Version (set to 0x00020000). */
diff --git a/src/hb-aat-gcid-table.hh b/src/hb-aat-gcid-table.hh
index 01c2c5c3..b48a2798 100644
--- a/src/hb-aat-gcid-table.hh
+++ b/src/hb-aat-gcid-table.hh
@@ -44,7 +44,7 @@ struct gcid
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && CIDs.sanitize (c));
+    return_trace (likely (c->check_struct (this) && CIDs.sanitize (c)));
   }
 
   protected:
diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh
index dc6582b6..3b7912b9 100644
--- a/src/hb-aat-layout-ankr-table.hh
+++ b/src/hb-aat-layout-ankr-table.hh
@@ -58,9 +58,10 @@ struct ankr
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && version == 0 &&
-		  lookupTable.sanitize (c, this) &&
-		  anchors.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+			  version == 0 &&
+			  lookupTable.sanitize (c, this) &&
+			  anchors.sanitize (c, this)));
   }
 
   protected:
diff --git a/src/hb-aat-layout-bsln-table.hh b/src/hb-aat-layout-bsln-table.hh
index a35b4483..df2bf5b4 100644
--- a/src/hb-aat-layout-bsln-table.hh
+++ b/src/hb-aat-layout-bsln-table.hh
@@ -42,7 +42,7 @@ struct BaselineTableFormat0Part
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   protected:
@@ -60,7 +60,8 @@ struct BaselineTableFormat1Part
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && lookupTable.sanitize (c));
+    return_trace (likely (c->check_struct (this) &&
+			  lookupTable.sanitize (c)));
   }
 
   protected:
@@ -77,7 +78,7 @@ struct BaselineTableFormat2Part
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   protected:
@@ -120,7 +121,7 @@ struct bsln
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!(c->check_struct (this) && defaultBaseline < 32))
+    if (unlikely (!(c->check_struct (this) && defaultBaseline < 32)))
       return_trace (false);
 
     switch (format) {
diff --git a/src/hb-aat-layout-feat-table.hh b/src/hb-aat-layout-feat-table.hh
index e7329fe1..3e070d79 100644
--- a/src/hb-aat-layout-feat-table.hh
+++ b/src/hb-aat-layout-feat-table.hh
@@ -42,7 +42,7 @@ struct SettingName
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   protected:
@@ -57,8 +57,8 @@ struct FeatureName
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  (base+settingTable).sanitize (c, nSettings));
+    return_trace (likely (c->check_struct (this) &&
+			  (base+settingTable).sanitize (c, nSettings)));
   }
 
   enum {
@@ -98,8 +98,8 @@ struct feat
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  names.sanitize (c, featureNameCount, this));
+    return_trace (likely (c->check_struct (this) &&
+			  names.sanitize (c, featureNameCount, this)));
   }
 
   protected:
diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 756faeff..5004f27f 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -147,7 +147,7 @@ struct KerxSubTableFormat2
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      rowWidth.sanitize (c) &&
+		  rowWidth.sanitize (c) &&
 		  leftClassTable.sanitize (c, this) &&
 		  rightClassTable.sanitize (c, this) &&
 		  array.sanitize (c, this));
@@ -174,7 +174,7 @@ struct KerxSubTableFormat4
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      rowWidth.sanitize (c) &&
+		  rowWidth.sanitize (c) &&
 		  leftClassTable.sanitize (c, this) &&
 		  rightClassTable.sanitize (c, this) &&
 		  array.sanitize (c, this));
@@ -241,7 +241,7 @@ struct KerxTable
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!c->check_struct (this))
+    if (unlikely (!c->check_struct (this)))
       return_trace (false);
 
     switch (format) {
@@ -301,18 +301,18 @@ struct kerx
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!(c->check_struct (this)))
+    if (unlikely (!(c->check_struct (this))))
      return_trace (false);
 
     /* TODO: Something like `morx`s ChainSubtable should be done here instead */
     const KerxTable *table = &StructAfter<KerxTable> (*this);
-    if (!(table->sanitize (c)))
+    if (unlikely (!(table->sanitize (c))))
       return_trace (false);
 
     for (unsigned int i = 0; i < nTables - 1; ++i)
     {
       table = &StructAfter<KerxTable> (*table);
-      if (!(table->sanitize (c)))
+      if (unlikely (!(table->sanitize (c))))
         return_trace (false);
     }
 
diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index 70f551a8..d093c1c7 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -44,12 +44,17 @@ namespace AAT {
 
 struct TrackTableEntry
 {
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, unsigned int size) const
+  friend struct TrackData;
+
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base,
+			unsigned int size) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && (values.sanitize (c, base, size)));
+    return_trace (likely (c->check_struct (this) &&
+			  (valuesZ.sanitize (c, base, size))));
   }
 
+  private:
   inline float get_track_value () const
   {
     return track.to_float ();
@@ -57,14 +62,14 @@ struct TrackTableEntry
 
   inline int get_value (const void *base, unsigned int index) const
   {
-    return (base+values)[index];
+    return (base+valuesZ)[index];
   }
 
   protected:
   Fixed		track;		/* Track value for this record. */
   NameID	trackNameID;	/* The 'name' table index for this track */
   OffsetTo<UnsizedArrayOf<FWORD> >
-		values;		/* Offset from start of tracking table to
+		valuesZ;	/* Offset from start of tracking table to
 				 * per-size tracking values for this track. */
 
   public:
@@ -146,9 +151,9 @@ struct trak
   {
     TRACE_SANITIZE (this);
 
-    return_trace (c->check_struct (this) &&
-		  horizData.sanitize (c, this, this) &&
-		  vertData.sanitize (c, this, this));
+    return_trace (unlikely (c->check_struct (this) &&
+			    horizData.sanitize (c, this, this) &&
+			    vertData.sanitize (c, this, this)));
   }
 
   inline bool apply (hb_aat_apply_context_t *c) const
@@ -156,7 +161,7 @@ struct trak
     TRACE_APPLY (this);
 
     const float ptem = c->font->ptem;
-    if (ptem <= 0.f)
+    if (unlikely (ptem <= 0.f))
       return_trace (false);
 
     hb_buffer_t *buffer = c->buffer;
diff --git a/src/hb-aat-ltag-table.hh b/src/hb-aat-ltag-table.hh
index 0796c671..15c4e89c 100644
--- a/src/hb-aat-ltag-table.hh
+++ b/src/hb-aat-ltag-table.hh
@@ -61,7 +61,7 @@ struct ltag
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && tagRanges.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) && tagRanges.sanitize (c, this)));
   }
 
   protected:
diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh
index 4d761fca..ce6702d2 100644
--- a/src/hb-ot-color-colr-table.hh
+++ b/src/hb-ot-color-colr-table.hh
@@ -61,7 +61,7 @@ struct BaseGlyphRecord
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   inline int cmp (hb_codepoint_t g) const {
@@ -90,9 +90,9 @@ struct COLR
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
-		  (this+layersZ).sanitize (c, numLayers));
+    return_trace (likely (c->check_struct (this) &&
+			  (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
+			  (this+layersZ).sanitize (c, numLayers)));
   }
 
   inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
@@ -102,7 +102,7 @@ struct COLR
     const BaseGlyphRecord* record;
     record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
 					  sizeof (BaseGlyphRecord), compare_bgr);
-    if (!record)
+    if (unlikely (!record))
       return false;
 
     *first_layer = record->firstLayerIdx;
diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh
index cb98f7d6..2c312748 100644
--- a/src/hb-ot-color-cpal-table.hh
+++ b/src/hb-ot-color-cpal-table.hh
@@ -143,13 +143,14 @@ struct CPAL
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!(c->check_struct (this) && // it checks colorRecordIndices also, see #get_size
-	  (this+colorRecordsZ).sanitize (c, numColorRecords)))
+    if (unlikely (!(c->check_struct (this) &&	// it checks colorRecordIndices also
+						// see #get_size
+		    (this+colorRecordsZ).sanitize (c, numColorRecords))))
       return_trace (false);
 
     // Check for indices sanity so no need for doing it runtime
     for (unsigned int i = 0; i < numPalettes; ++i)
-      if (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords)
+      if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords))
 	return_trace (false);
 
     // If version is zero, we are done here; otherwise we need to check tail also
@@ -157,7 +158,7 @@ struct CPAL
       return_trace (true);
 
     const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this);
-    return_trace (v1.sanitize (c, this, numPalettes));
+    return_trace (likely (v1.sanitize (c, this, numPalettes)));
   }
 
   inline unsigned int get_size (void) const
@@ -167,7 +168,7 @@ struct CPAL
 
   inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const
   {
-    if (version == 0 || palette >= numPalettes)
+    if (unlikely (version == 0 || palette >= numPalettes))
       return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
 
     const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
@@ -176,7 +177,7 @@ struct CPAL
 
   inline unsigned int get_palette_name_id (unsigned int palette) const
   {
-    if (version == 0 || palette >= numPalettes)
+    if (unlikely (version == 0 || palette >= numPalettes))
       return 0xFFFF;
 
     const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
@@ -191,11 +192,12 @@ struct CPAL
   inline hb_ot_color_t
   get_color_record_argb (unsigned int color_index, unsigned int palette) const
   {
-    if (color_index >= numPaletteEntries || palette >= numPalettes)
+    if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes))
       return 0;
 
     // No need for more range check as it is already done on #sanitize
-    return (this+colorRecordsZ)[colorRecordIndicesZ[palette] + color_index];
+    const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ;
+    return color_records[colorRecordIndicesZ[palette] + color_index];
   }
 
   protected:
diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh
index 7dea6140..09d0cc57 100644
--- a/src/hb-ot-color-sbix-table.hh
+++ b/src/hb-ot-color-sbix-table.hh
@@ -89,7 +89,7 @@ struct sbix
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && strikes.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) && strikes.sanitize (c, this)));
   }
 
   struct accelerator_t
diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh
index 1357b788..47b3292b 100644
--- a/src/hb-ot-color-svg-table.hh
+++ b/src/hb-ot-color-svg-table.hh
@@ -71,7 +71,7 @@ struct SVGDocumentIndex
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      entries.sanitize (c, this));
+		  entries.sanitize (c, this));
   }
 
   protected:
@@ -88,8 +88,8 @@ struct SVG
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-		  (this+svgDocIndex).sanitize (c));
+    return_trace (likely (c->check_struct (this) &&
+			  (this+svgDocIndex).sanitize (c)));
   }
 
   struct accelerator_t
commit 1a309dcd72f9f54672a7341788a9b2241c922793
Author: Garret Rieger <grieger at google.com>
Date:   Tue Apr 17 18:11:32 2018 -0700

    [subset] Remove printf's from fuzzing targets.

diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index 1e26d26a..dfa83613 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -8,7 +8,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);
diff --git a/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc b/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc
index c20b1fc8..38f338ba 100644
--- a/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc
+++ b/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc
@@ -8,7 +8,6 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 {
-  printf ("hb-subset-get-codepoints-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 c55aa147c33eb733ab552d404a88749cb6ff6d73
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Wed Apr 18 00:01:20 2018 +0430

    Do sanitization before the use on 'main' mini-program (#994)

diff --git a/src/main.cc b/src/main.cc
index d221e9da..9423a728 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -51,11 +51,15 @@ main (int argc, char **argv)
 
   const char *font_data = nullptr;
   int len = 0;
+  hb_destroy_func_t destroy;
+  hb_memory_mode_t mm;
 
 #ifdef HAVE_GLIB
   GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr);
   font_data = g_mapped_file_get_contents (mf);
   len = g_mapped_file_get_length (mf);
+  destroy = (hb_destroy_func_t) g_mapped_file_unref;
+  mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
 #else
   FILE *f = fopen (argv[1], "rb");
   fseek (f, 0, SEEK_END);
@@ -63,11 +67,23 @@ main (int argc, char **argv)
   fseek (f, 0, SEEK_SET);
   font_data = (const char *) malloc (len);
   len = fread ((char *) font_data, 1, len, f);
+  destroy = free;
+  mm = HB_MEMORY_MODE_WRITABLE;
 #endif
 
   printf ("Opened font file %s: %d bytes long\n", argv[1], len);
 
-  const OpenTypeFontFile &ot = *CastP<OpenTypeFontFile> (font_data);
+  Sanitizer<OpenTypeFontFile> sanitizer;
+  hb_blob_t *blob = hb_blob_create (font_data, len, mm, (void *) font_data, destroy);
+  hb_blob_t *font_blob = sanitizer.sanitize (blob);
+  const OpenTypeFontFile* sanitized = Sanitizer<OpenTypeFontFile>::lock_instance (font_blob);
+  if (sanitized == &Null (OpenTypeFontFile))
+  {
+    printf ("Sanitization of the file wasn't successful. Exit");
+    return 1;
+  }
+  const OpenTypeFontFile& ot = *sanitized;
+
 
   switch (ot.get_tag ()) {
   case OpenTypeFontFile::TrueTypeTag:
@@ -101,7 +117,7 @@ main (int argc, char **argv)
     for (int n_table = 0; n_table < num_tables; n_table++) {
       const OpenTypeTable &table = font.get_table (n_table);
       printf ("  Table %2d of %2d: %.4s (0x%08x+0x%08x)\n", n_table, num_tables,
-	      (const char *)table.tag,
+	      (const char *) table.tag,
 	      (unsigned int) table.offset,
 	      (unsigned int) table.length);
 
@@ -197,5 +213,3 @@ main (int argc, char **argv)
 
   return 0;
 }
-
-
commit c02b40e58f35ecd10c4945d2fa2b7074137c2c04
Author: Garret Rieger <grieger at google.com>
Date:   Tue Apr 17 08:21:22 2018 -0600

    [subset] add a fuzzer target for subset_get_all_codepoints method. (#987)

diff --git a/test/fuzzing/CMakeLists.txt b/test/fuzzing/CMakeLists.txt
index 577d13ce..2a45ef64 100644
--- a/test/fuzzing/CMakeLists.txt
+++ b/test/fuzzing/CMakeLists.txt
@@ -2,6 +2,7 @@ if (HB_CHECK)
   file (READ "${CMAKE_CURRENT_SOURCE_DIR}/Makefile.am" MAKEFILEAM)
   extract_make_variable (hb_shape_fuzzer_SOURCES ${MAKEFILEAM})
   extract_make_variable (hb_subset_fuzzer_SOURCES ${MAKEFILEAM})
+  extract_make_variable (hb_subset_get_codepoints_fuzzer_SOURCES ${MAKEFILEAM})
 
   # TODO: enable these two
   #extract_make_variable (FUZZING_CPPFLAGS ${MAKEFILEAM}) # extracting regex fail
@@ -15,13 +16,17 @@ if (HB_CHECK)
   add_executable (hb-subset-fuzzer ${hb_subset_fuzzer_SOURCES})
   target_link_libraries (hb-subset-fuzzer harfbuzz-subset)
 
+  add_executable (hb-subset-get-codepoints-fuzzer ${hb_subset_get_codepoints_fuzzer_SOURCES})
+  target_link_libraries (hb-subset-get-codepoints-fuzzer harfbuzz-subset)
+
   target_compile_definitions(hb-shape-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
   target_compile_definitions(hb-subset-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
+  target_compile_definitions(hb-subset-get-codepoints-fuzzer PUBLIC ${FUZZING_CPPFLAGS})
 
   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>
+    COMMAND "${PYTHON_EXECUTABLE}" run-subset-fuzzer-tests.py $<TARGET_FILE:hb-subset-fuzzer> $<TARGET_FILE:hb-subset-get-codepoints-fuzzer>
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 endif ()
diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am
index a57f41dc..5af5a733 100644
--- a/test/fuzzing/Makefile.am
+++ b/test/fuzzing/Makefile.am
@@ -23,6 +23,7 @@ EXTRA_DIST += \
 check_PROGRAMS = \
 	hb-shape-fuzzer \
 	hb-subset-fuzzer \
+	hb-subset-get-codepoints-fuzzer \
 	$(NULL)
 
 AM_CPPFLAGS = \
@@ -64,6 +65,21 @@ hb_subset_fuzzer_DEPENDENCIES = \
 	lib \
 	$(NULL)
 
+hb_subset_get_codepoints_fuzzer_SOURCES = \
+	hb-fuzzer.hh \
+	hb-subset-get-codepoints-fuzzer.cc \
+	main.cc \
+	$(NULL)
+hb_subset_get_codepoints_fuzzer_LDADD = \
+	$(top_builddir)/src/libharfbuzz-subset-fuzzing.la \
+	$(NULL)
+hb_subset_get_codepoints_fuzzer_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	$(NULL)
+hb_subset_get_codepoints_fuzzer_DEPENDENCIES = \
+	lib \
+	$(NULL)
+
 check:
 	EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-shape-fuzzer-tests.py
 	EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-subset-fuzzer-tests.py
diff --git a/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc b/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc
new file mode 100644
index 00000000..c20b1fc8
--- /dev/null
+++ b/test/fuzzing/hb-subset-get-codepoints-fuzzer.cc
@@ -0,0 +1,24 @@
+#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)
+{
+  printf ("hb-subset-get-codepoints-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);
+
+  hb_set_t *output = hb_set_create();
+  hb_subset_get_all_codepoints (face, output);
+
+  hb_set_destroy (output);
+  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 23575231..01362886 100755
--- a/test/fuzzing/run-subset-fuzzer-tests.py
+++ b/test/fuzzing/run-subset-fuzzer-tests.py
@@ -8,15 +8,24 @@ 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_get_codepoints_fuzzer = os.path.join (top_builddir, "hb-subset-get-codepoints-fuzzer" + EXEEXT)
 
 if not os.path.exists (hb_subset_fuzzer):
-        if len (sys.argv) == 1 or not os.path.exists (sys.argv[1]):
+        if len (sys.argv) < 2 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]
 
+if not os.path.exists (hb_subset_get_codepoints_fuzzer):
+        if len (sys.argv) < 3 or not os.path.exists (sys.argv[2]):
+                print ("""Failed to find hb-subset-get-codepoints-fuzzer binary automatically,
+please provide it as the second argument to the tool""")
+                sys.exit (1)
+
+        hb_subset_get_codepoints_fuzzer = sys.argv[2]
+
 print ('hb_subset_fuzzer:', hb_subset_fuzzer)
 fails = 0
 
@@ -24,6 +33,7 @@ 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):
         path = os.path.join(parent_path, file)
+
         print ("running subset fuzzer against %s" % path)
         p = subprocess.Popen ([hb_subset_fuzzer, path])
 
@@ -31,6 +41,13 @@ for file in os.listdir (parent_path):
                 print ("failed for %s" % path)
                 fails = fails + 1
 
+        print ("running subset get codepoints fuzzer against %s" % path)
+        p = subprocess.Popen ([hb_subset_get_codepoints_fuzzer, path])
+
+        if p.wait () != 0:
+                print ("failed for %s" % path)
+                fails = fails + 1
+
 if fails:
         print ("%i subset fuzzer related tests failed." % fails)
         sys.exit (1)


More information about the HarfBuzz mailing list