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