diff --git a/src/hb-ot-cff-common-private.hh b/src/hb-ot-cff-common-private.hh index fde100ad4..9dab98dac 100644 --- a/src/hb-ot-cff-common-private.hh +++ b/src/hb-ot-cff-common-private.hh @@ -23,8 +23,8 @@ * * Adobe Author(s): Michiharu Ariza */ -#ifndef HB_OT_CFF_COMMON_HH -#define HB_OT_CFF_COMMON_HH +#ifndef HB_OT_CFF_COMMON_PRIVATE_HH +#define HB_OT_CFF_COMMON_PRIVATE_HH #include "hb-open-type-private.hh" #include "hb-ot-layout-common-private.hh" @@ -140,9 +140,9 @@ struct Index inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && offSize >= 1 && offSize <= 4 && - c->check_array (offsets, offSize, count + 1) && - c->check_array (data_base (), 1, offset_at (count))); + return_trace (likely (c->check_struct (this) && offSize >= 1 && offSize <= 4 && + c->check_array (offsets, offSize, count + 1) && + c->check_array (data_base (), 1, max_offset () - 1))); } inline unsigned int offset_array_size (void) const @@ -182,6 +182,19 @@ struct Index inline unsigned int get_size (void) const { return count.static_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1); } + protected: + inline unsigned int max_offset (void) const + { + unsigned int max = 0; + for (unsigned int i = 0; i <= count; i++) + { + unsigned int off = offset_at (i); + if (off > max) max = off; + } + return max; + } + + public: HBUINT32 count; /* Number of object data. Note there are (count+1) offsets */ HBUINT8 offSize; /* The byte size of each offset in the offsets array. */ HBUINT8 offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */ @@ -193,14 +206,6 @@ struct Index template struct IndexOf : Index { - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && offSize >= 1 && offSize <= 4 && - c->check_array (offsets, offSize, count + 1) && - c->check_array (data_base (), sizeof (Type), offset_at (count))); - } - inline const Type& operator [] (unsigned int index) const { if (likely (index < count)) @@ -235,27 +240,59 @@ typedef IndexOf FDArray; /* FDSelect */ struct FDSelect0 { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + } + HBUINT8 fds[VAR]; + + DEFINE_SIZE_MIN (1); }; struct FDSelect3_Range { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && (first < c->get_num_glyphs ()))); + } + HBUINT16 first; HBUINT8 fd; + + DEFINE_SIZE_STATIC (3); }; struct FDSelect3 { + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && (nRanges > 0) && + (ranges[nRanges - 1].sanitize (c)))); + } + HBUINT16 nRanges; FDSelect3_Range ranges[VAR]; /* HBUINT16 sentinel */ + + DEFINE_SIZE_MIN (5); }; struct FDSelect { - // XXX: need to sanitize at run time + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) && + (format == 0)? u.format0.sanitize (c): u.format3.sanitize (c))); + } + HBUINT8 format; union { FDSelect0 format0; FDSelect3 format3; } u; + + DEFINE_SIZE_MIN (2); }; inline float parse_bcd (const ByteStr& str, unsigned int& offset, float& v) @@ -471,5 +508,5 @@ struct Interpreter { } /* namespace CFF */ -#endif /* HB_OT_CFF_COMMON_HH */ +#endif /* HB_OT_CFF_COMMON_PRIVATE_HH */ diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh index 2f495915b..5abfc7814 100644 --- a/src/hb-ot-cff2-table.hh +++ b/src/hb-ot-cff2-table.hh @@ -289,7 +289,6 @@ struct cff2 { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - version.sanitize (c) && likely (version.major == 2)); } @@ -297,17 +296,23 @@ struct cff2 { inline void init (hb_face_t *face) { - this->blob = OT::Sanitizer().sanitize (face->reference_table (HB_OT_TAG_cff2)); + hb_sanitize_context_t c; + this->blob = c.reference_table (face); const OT::cff2 *cff2 = this->blob->as (); if (cff2 == &Null(OT::cff2)) { - hb_blob_destroy (blob); + fini (); return; } { /* parse top dict */ ByteStr topDictStr (cff2 + cff2->topDict, cff2->topDictSize); + if (unlikely (!topDictStr.sanitize (&c))) + { + fini (); + return; + } CFF2TopDict_Interpreter top_interp; top_interp.init (); top_interp.interpret (topDictStr, top); @@ -319,20 +324,27 @@ struct cff2 fdArray = &OT::StructAtOffset(cff2, top.FDArrayOffset); fdSelect = &OT::StructAtOffset(cff2, top.FDSelectOffset); - // XXX: sanitize above? - if ((charStrings == &Null(CharStrings)) || - (fdArray == &Null(FDArray))) + if (((varStore != &Null(VariationStore)) && unlikely (!varStore->sanitize (&c))) || + ((charStrings == &Null(CharStrings)) || unlikely (!charStrings->sanitize (&c))) || + ((fdArray == &Null(FDArray)) || unlikely (!fdArray->sanitize (&c))) || + ((fdSelect == &Null(FDSelect)) || unlikely (!fdSelect->sanitize (&c)))) { - hb_blob_destroy (blob); + fini (); return; } num_glyphs = charStrings->count; + if (num_glyphs != c.get_num_glyphs ()) + { + fini (); + return; + } } inline void fini (void) { hb_blob_destroy (blob); + blob = nullptr; } inline bool get_extents (hb_codepoint_t glyph, diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc index 7ec15466e..66681e975 100644 --- a/src/hb-subset-cff2.cc +++ b/src/hb-subset-cff2.cc @@ -104,7 +104,7 @@ bool hb_subset_cff2 (hb_subset_plan_t *plan, hb_blob_t **cff2_prime /* OUT */) { - hb_blob_t *cff2_blob = OT::Sanitizer().sanitize (plan->source->reference_table (HB_OT_TAG_cff2)); + hb_blob_t *cff2_blob = OT::hb_sanitize_context_t().reference_table (plan->source); const char *cff2_data = hb_blob_get_data(cff2_blob, nullptr); OT::cff2::accelerator_t cff2;