src/hb-open-type-private.hh                                             |   28 
+++++-
 src/hb-ot-layout-gpos-table.hh                                          |   15 
+--
 src/hb-ot-layout-gsub-table.hh                                          |   13 
+-
 src/hb-ot-layout-gsubgpos-private.hh                                    |   44 
+++-------
 src/hb-ot-layout.cc                                                     |    8 
-
 test/shaping/Makefile.am                                                |    1 
 test/shaping/fonts/sha1sum/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf |binary
 test/shaping/fonts/sha1sum/MANIFEST                                     |    1 
 test/shaping/tests/MANIFEST                                             |    1 
 test/shaping/tests/fuzzed.tests                                         |    1 
 10 files changed, 60 insertions(+), 52 deletions(-)

New commits:
commit 34379b49e6922b86c15ee62f7fe3bf016cdc2514
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Fri Oct 9 12:34:02 2015 -0400

    Add test for previous fix

diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am
index e34d83b..5694572 100644
--- a/test/shaping/Makefile.am
+++ b/test/shaping/Makefile.am
@@ -46,6 +46,7 @@ TESTS = \
        tests/context-matching.tests \
        tests/cursive-positioning.tests \
        tests/default-ignorables.tests \
+       tests/fuzzed.tests \
        tests/hangul-jamo.tests \
        tests/indic-joiner-candrabindu.tests \
        tests/indic-old-spec.tests \
diff --git 
a/test/shaping/fonts/sha1sum/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf 
b/test/shaping/fonts/sha1sum/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf
new file mode 100644
index 0000000..c71e85a
Binary files /dev/null and 
b/test/shaping/fonts/sha1sum/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf differ
diff --git a/test/shaping/fonts/sha1sum/MANIFEST 
b/test/shaping/fonts/sha1sum/MANIFEST
index 1de86c8..2bb1883 100644
--- a/test/shaping/fonts/sha1sum/MANIFEST
+++ b/test/shaping/fonts/sha1sum/MANIFEST
@@ -1,5 +1,6 @@
 051d92f8bc6ff724511b296c27623f824de256e9.ttf
 191826b9643e3f124d865d617ae609db6a2ce203.ttf
+1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf
 226bc2deab3846f1a682085f70c67d0421014144.ttf
 270b89df543a7e48e206a2d830c0e10e5265c630.ttf
 298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttf
diff --git a/test/shaping/tests/MANIFEST b/test/shaping/tests/MANIFEST
index b4ee18e..6ae62dc 100644
--- a/test/shaping/tests/MANIFEST
+++ b/test/shaping/tests/MANIFEST
@@ -4,6 +4,7 @@ cluster.tests
 context-matching.tests
 cursive-positioning.tests
 default-ignorables.tests
+fuzzed.tests
 hangul-jamo.tests
 indic-joiner-candrabindu.tests
 indic-old-spec.tests
diff --git a/test/shaping/tests/fuzzed.tests b/test/shaping/tests/fuzzed.tests
new file mode 100644
index 0000000..3110d7d
--- /dev/null
+++ b/test/shaping/tests/fuzzed.tests
@@ -0,0 +1 @@
+fonts/sha1sum/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf::U+0041:[gid0=0+1000]
commit f396fbb000dc1c8acddbf6a16e193b328c5e551e
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Fri Oct 9 12:25:55 2015 -0400

    Fix return value of sanitize when subformat is not readable
    
    This is a fix on top of the previous issue fixed in
    c917965b9e6fe2b21ed6c51559673288fa3af4b7.
    
    This was caught by "libFuzzer" testing.

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index e5c4c0d..aeb3302 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -165,6 +165,7 @@ struct hb_dispatch_context_t
   typedef Return return_t;
   template <typename T, typename F>
   inline bool may_dispatch (const T *obj, const F *format) { return true; }
+  static return_t no_dispatch_return_value (void) { return 
Context::default_return_value (); }
 };
 
 
@@ -203,6 +204,7 @@ struct hb_sanitize_context_t :
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
   static return_t default_return_value (void) { return true; }
+  static return_t no_dispatch_return_value (void) { return false; }
   bool stop_sublookup_iteration (const return_t r) const { return !r; }
 
   inline void init (hb_blob_t *b)
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 286253d..ca98cb7 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -548,7 +548,7 @@ struct SinglePos
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     case 2: return_trace (c->dispatch (u.format2));
@@ -843,7 +843,7 @@ struct PairPos
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     case 2: return_trace (c->dispatch (u.format2));
@@ -1024,7 +1024,7 @@ struct CursivePos
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
@@ -1120,7 +1120,7 @@ struct MarkBasePos
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
@@ -1238,7 +1238,7 @@ struct MarkLigPos
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
@@ -1353,7 +1353,7 @@ struct MarkMarkPos
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
@@ -1404,8 +1404,7 @@ struct PosLookupSubTable
   inline typename context_t::return_t dispatch (context_t *c, unsigned int 
lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    /* The sub_format passed to may_dispatch is unnecessary but harmless. */
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace 
(c->no_dispatch_return_value ());
     switch (lookup_type) {
     case Single:               return_trace (u.single.dispatch (c));
     case Pair:                 return_trace (u.pair.dispatch (c));
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index c578254..eebc87b 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -225,7 +225,7 @@ struct SingleSubst
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     case 2: return_trace (c->dispatch (u.format2));
@@ -418,7 +418,7 @@ struct MultipleSubst
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
@@ -562,7 +562,7 @@ struct AlternateSubst
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
@@ -878,7 +878,7 @@ struct LigatureSubst
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
@@ -1035,7 +1035,7 @@ struct ReverseChainSingleSubst
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     default:return_trace (c->default_return_value ());
@@ -1074,8 +1074,7 @@ struct SubstLookupSubTable
   inline typename context_t::return_t dispatch (context_t *c, unsigned int 
lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    /* The sub_format passed to may_dispatch is unnecessary but harmless. */
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace 
(c->no_dispatch_return_value ());
     switch (lookup_type) {
     case Single:               return_trace (u.single.dispatch (c));
     case Multiple:             return_trace (u.multiple.dispatch (c));
diff --git a/src/hb-ot-layout-gsubgpos-private.hh 
b/src/hb-ot-layout-gsubgpos-private.hh
index 65e39a6..2a9f444 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -1505,7 +1505,7 @@ struct Context
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     case 2: return_trace (c->dispatch (u.format2));
@@ -2120,7 +2120,7 @@ struct ChainContext
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (c->dispatch (u.format1));
     case 2: return_trace (c->dispatch (u.format2));
@@ -2156,7 +2156,7 @@ struct ExtensionFormat1
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, format);
-    if (unlikely (!c->may_dispatch (this, this))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, this))) return_trace 
(c->no_dispatch_return_value ());
     return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, 
get_type ()));
   }
 
@@ -2201,7 +2201,7 @@ struct Extension
   inline typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->default_return_value ());
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace 
(c->no_dispatch_return_value ());
     switch (u.format) {
     case 1: return_trace (u.format1.dispatch (c));
     default:return_trace (c->default_return_value ());
commit 77a1a2bc18e7b04d4e352a8777ccce345b2f8659
Author: Behdad Esfahbod <beh...@behdad.org>
Date:   Fri Oct 9 12:20:58 2015 -0400

    Add hb_dispatch_context_t

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 79e70b8..e5c4c0d 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -154,6 +154,19 @@ ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
 #define Null(Type) Null<Type>()
 
 
+/*
+ * Dispatch
+ */
+
+template <typename Context, typename Return, unsigned int MaxDebugDepth>
+struct hb_dispatch_context_t
+{
+  static const unsigned int max_debug_depth = MaxDebugDepth;
+  typedef Return return_t;
+  template <typename T, typename F>
+  inline bool may_dispatch (const T *obj, const F *format) { return true; }
+};
+
 
 /*
  * Sanitize
@@ -174,11 +187,16 @@ ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type))
 #define HB_SANITIZE_MAX_EDITS 100
 #endif
 
-struct hb_sanitize_context_t
+struct hb_sanitize_context_t :
+       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
 {
+  inline hb_sanitize_context_t (void) :
+       debug_depth (0),
+       start (NULL), end (NULL),
+       writable (false), edit_count (0),
+       blob (NULL) {}
+
   inline const char *get_name (void) { return "SANITIZE"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE;
-  typedef bool return_t;
   template <typename T, typename F>
   inline bool may_dispatch (const T *obj, const F *format)
   { return format->sanitize (this); }
@@ -295,7 +313,7 @@ template <typename Type>
 struct Sanitizer
 {
   static hb_blob_t *sanitize (hb_blob_t *blob) {
-    hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}};
+    hb_sanitize_context_t c[1];
     bool sane;
 
     /* TODO is_sane() stuff */
diff --git a/src/hb-ot-layout-gsubgpos-private.hh 
b/src/hb-ot-layout-gsubgpos-private.hh
index 6cf1ffc..65e39a6 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -46,14 +46,11 @@ namespace OT {
        (&c->debug_depth, c->get_name (), this, HB_FUNC, \
         "");
 
-struct hb_closure_context_t
+struct hb_closure_context_t :
+       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
 {
   inline const char *get_name (void) { return "CLOSURE"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE;
-  typedef hb_void_t return_t;
   typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int 
lookup_index);
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { obj.closure (this); return 
HB_VOID; }
   static return_t default_return_value (void) { return HB_VOID; }
@@ -98,13 +95,10 @@ struct hb_closure_context_t
        (&c->debug_depth, c->get_name (), this, HB_FUNC, \
         "%d glyphs", c->len);
 
-struct hb_would_apply_context_t
+struct hb_would_apply_context_t :
+       hb_dispatch_context_t<hb_would_apply_context_t, bool, 
HB_DEBUG_WOULD_APPLY>
 {
   inline const char *get_name (void) { return "WOULD_APPLY"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
-  typedef bool return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
   static return_t default_return_value (void) { return false; }
@@ -138,14 +132,11 @@ struct hb_would_apply_context_t
        (&c->debug_depth, c->get_name (), this, HB_FUNC, \
         "");
 
-struct hb_collect_glyphs_context_t
+struct hb_collect_glyphs_context_t :
+       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, 
HB_DEBUG_COLLECT_GLYPHS>
 {
   inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS;
-  typedef hb_void_t return_t;
   typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned 
int lookup_index);
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return 
HB_VOID; }
   static return_t default_return_value (void) { return HB_VOID; }
@@ -232,14 +223,14 @@ struct hb_collect_glyphs_context_t
 #define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
 #endif
 
+/* XXX Can we remove this? */
+
 template <typename set_t>
-struct hb_add_coverage_context_t
+struct hb_add_coverage_context_t :
+       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage 
&, HB_DEBUG_GET_COVERAGE>
 {
   inline const char *get_name (void) { return "GET_COVERAGE"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE;
   typedef const Coverage &return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
   static return_t default_return_value (void) { return Null(Coverage); }
@@ -269,7 +260,8 @@ struct hb_add_coverage_context_t
         "idx %d gid %u lookup %d", \
         c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index);
 
-struct hb_apply_context_t
+struct hb_apply_context_t :
+       hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY>
 {
   struct matcher_t
   {
@@ -449,11 +441,7 @@ struct hb_apply_context_t
 
 
   inline const char *get_name (void) { return "APPLY"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
-  typedef bool return_t;
   typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int 
lookup_index);
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return obj.apply (this); }
   static return_t default_return_value (void) { return false; }
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 1a6fb15..275a960 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -28,6 +28,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
+#include "hb-open-type-private.hh"
 #include "hb-ot-layout-private.hh"
 
 #include "hb-ot-layout-gdef-table.hh"
@@ -925,13 +926,10 @@ apply_backward (OT::hb_apply_context_t *c,
   return ret;
 }
 
-struct hb_apply_forward_context_t
+struct hb_apply_forward_context_t :
+       OT::hb_dispatch_context_t<hb_apply_forward_context_t, bool, 
HB_DEBUG_APPLY>
 {
   inline const char *get_name (void) { return "APPLY_FWD"; }
-  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
-  typedef bool return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
   template <typename T>
   inline return_t dispatch (const T &obj) { return apply_forward (c, obj, 
accel); }
   static return_t default_return_value (void) { return false; }
_______________________________________________
HarfBuzz mailing list
HarfBuzz@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/harfbuzz

Reply via email to