From 0d2727f4fe734af146785df10a44e3505e410ba1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 14 Jan 2019 18:23:17 -0800 Subject: [PATCH] fix FDSelect fuzzing bug (#1539) Rewrote struct FDSelect3_4.ranges as ArrayOf Updated FDSelect3_4::sanitize () to call ranges.sanitize () nRanges now a function to return a reference to ranges.len --- src/hb-ot-cff-common.hh | 29 +++++++++++++++-------------- src/hb-subset-cff-common.cc | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh index 3a9cce3..c645953 100644 --- a/src/hb-ot-cff-common.hh +++ b/src/hb-ot-cff-common.hh @@ -588,10 +588,10 @@ struct FDSelect0 { template struct FDSelect3_4_Range { - bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const + bool sanitize (hb_sanitize_context_t *c, const void */*nullptr*/, unsigned int fdcount) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && (first < c->get_num_glyphs ()) && (fd < fdcount))); + return_trace (first < c->get_num_glyphs () && (fd < fdcount)); } GID_TYPE first; @@ -603,21 +603,21 @@ struct FDSelect3_4_Range { template struct FDSelect3_4 { unsigned int get_size () const - { return GID_TYPE::static_size * 2 + FDSelect3_4_Range::static_size * nRanges; } + { return GID_TYPE::static_size * 2 + ranges.get_size (); } bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const { TRACE_SANITIZE (this); - if (unlikely (!(c->check_struct (this) && (nRanges > 0) && (ranges[0].first == 0)))) + if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) || + (nRanges () == 0) || ranges[0].first != 0)) return_trace (false); - for (unsigned int i = 0; i < nRanges; i++) + for (unsigned int i = 1; i < nRanges (); i++) { - if (unlikely (!ranges[i].sanitize (c, fdcount))) - return_trace (false); - if ((0 < i) && unlikely (ranges[i - 1].first >= ranges[i].first)) - return_trace (false); + if (unlikely (ranges[i - 1].first >= ranges[i].first)) + return_trace (false); } + if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ()))) return_trace (false); @@ -627,18 +627,19 @@ struct FDSelect3_4 { hb_codepoint_t get_fd (hb_codepoint_t glyph) const { unsigned int i; - for (i = 1; i < nRanges; i++) + for (i = 1; i < nRanges (); i++) if (glyph < ranges[i].first) break; return (hb_codepoint_t)ranges[i - 1].fd; } - GID_TYPE &sentinel () { return StructAfter (ranges[nRanges - 1]); } - const GID_TYPE &sentinel () const { return StructAfter (ranges[nRanges - 1]); } + GID_TYPE &nRanges () { return ranges.len; } + GID_TYPE nRanges () const { return ranges.len; } + GID_TYPE &sentinel () { return StructAfter (ranges[nRanges () - 1]); } + const GID_TYPE &sentinel () const { return StructAfter (ranges[nRanges () - 1]); } - GID_TYPE nRanges; - FDSelect3_4_Range ranges[VAR]; + ArrayOf, GID_TYPE> ranges; /* GID_TYPE sentinel */ DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges); diff --git a/src/hb-subset-cff-common.cc b/src/hb-subset-cff-common.cc index 47efadf..3e617d5 100644 --- a/src/hb-subset-cff-common.cc +++ b/src/hb-subset-cff-common.cc @@ -153,7 +153,7 @@ serialize_fdselect_3_4 (hb_serialize_context_t *c, TRACE_SERIALIZE (this); FDSELECT3_4 *p = c->allocate_size (size); if (unlikely (p == nullptr)) return_trace (false); - p->nRanges.set (fdselect_ranges.length); + p->nRanges ().set (fdselect_ranges.length); for (unsigned int i = 0; i < fdselect_ranges.length; i++) { p->ranges[i].first.set (fdselect_ranges[i].glyph); -- 2.7.4