diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index def968eb7..eb15c089e 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -529,18 +529,20 @@ struct hb_array_t struct hb_bytes_t { - inline hb_bytes_t (void) : bytes (nullptr), len (0) {} - inline hb_bytes_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {} - inline hb_bytes_t (const void *bytes_, unsigned int len_) : bytes ((const char *) bytes_), len (len_) {} + inline hb_bytes_t (void) : arrayZ (nullptr), len (0) {} + inline hb_bytes_t (const char *bytes_, unsigned int len_) : arrayZ (bytes_), len (len_) {} + inline hb_bytes_t (const void *bytes_, unsigned int len_) : arrayZ ((const char *) bytes_), len (len_) {} + template + inline hb_bytes_t (const T& array) : arrayZ ((const char *) array.arrayZ), len (array.len) {} - inline void free (void) { ::free ((void *) bytes); bytes = nullptr; len = 0; } + inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } inline int cmp (const hb_bytes_t &a) const { if (len != a.len) return (int) a.len - (int) len; - return memcmp (a.bytes, bytes, len); + return memcmp (a.arrayZ, arrayZ, len); } static inline int cmp (const void *pa, const void *pb) { @@ -549,7 +551,7 @@ struct hb_bytes_t return b->cmp (*a); } - const char *bytes; + const char *arrayZ; unsigned int len; }; diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh index 39c6aeb89..a1f931d3c 100644 --- a/src/hb-open-file.hh +++ b/src/hb-open-file.hh @@ -287,52 +287,69 @@ struct TTCHeader /* * Mac Resource Fork + * + * http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html */ -struct ResourceRefItem +struct ResourceRecord { - inline bool sanitize (hb_sanitize_context_t *c) const + inline const OpenTypeFontFace & get_face (const void *data_base) const + { return CastR ((data_base+offset).arrayZ); } + + inline bool sanitize (hb_sanitize_context_t *c, + const void *data_base) const { TRACE_SANITIZE (this); - // actual data sanitization is done on ResourceForkHeader sanitizer - return_trace (likely (c->check_struct (this))); + return_trace (c->check_struct (this) && + offset.sanitize (c, data_base) && + get_face (data_base).sanitize (c)); } - HBINT16 id; /* Resource ID, is really should be signed? */ + protected: + HBUINT16 id; /* Resource ID. */ HBINT16 nameOffset; /* Offset from beginning of resource name list - * to resource name, minus means there is none. */ - HBUINT8 attr; /* Resource attributes */ - HBUINT24 dataOffset; /* Offset from beginning of resource data to + * to resource name, -1 means there is none. */ + HBUINT8 attrs; /* Resource attributes */ + OffsetTo, HBUINT24, false> + offset; /* Offset from beginning of data block to * data for this resource */ HBUINT32 reserved; /* Reserved for handle to resource */ public: DEFINE_SIZE_STATIC (12); }; -struct ResourceTypeItem +#define HB_TAG_sfnt HB_TAG ('s','f','n','t') + +struct ResourceTypeRecord { - inline bool sanitize (hb_sanitize_context_t *c) const + inline unsigned int get_resource_count (void) const + { return tag == HB_TAG_sfnt ? resCountM1 + 1 : 0; } + + inline bool is_sfnt (void) const { return tag == HB_TAG_sfnt; } + + inline const ResourceRecord& get_resource_record (unsigned int i, + const void *type_base) const { - TRACE_SANITIZE (this); - // RefList sanitization is done on ResourceMap sanitizer - return_trace (likely (c->check_struct (this))); + return hb_array_t ((type_base+resourcesZ).arrayZ, + get_resource_count ()) [i]; } - inline unsigned int get_resource_count () const { return numRes + 1; } - - inline bool is_sfnt () const { return type == HB_TAG ('s','f','n','t'); } - - inline const ResourceRefItem& get_ref_item (const void *base, - unsigned int i) const + inline bool sanitize (hb_sanitize_context_t *c, + const void *type_base, + const void *data_base) const { - return (base+refList)[i]; + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + resourcesZ.sanitize (c, type_base, + get_resource_count (), + data_base)); } protected: - Tag type; /* Resource type. */ - HBUINT16 numRes; /* Number of resources minus 1. */ - OffsetTo > - refList; /* Offset from beginning of resource type list + Tag tag; /* Resource type. */ + HBUINT16 resCountM1; /* Number of resources minus 1. */ + OffsetTo > + resourcesZ; /* Offset from beginning of resource type list * to reference item list for this type. */ public: DEFINE_SIZE_STATIC (8); @@ -340,132 +357,88 @@ struct ResourceTypeItem struct ResourceMap { - inline bool sanitize (hb_sanitize_context_t *c) const + inline unsigned int get_face_count (void) const { - TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) - return_trace (false); - for (unsigned int i = 0; i < get_types_count (); ++i) + unsigned int count = get_type_count (); + for (unsigned int i = 0; i < count; i++) { - const ResourceTypeItem& type = get_type (i); - if (unlikely (!type.sanitize (c))) - return_trace (false); - for (unsigned int j = 0; j < type.get_resource_count (); ++j) - if (unlikely (!get_ref_item (type, j).sanitize (c))) - return_trace (false); - } - return_trace (true); - } - - inline const ResourceTypeItem& get_type (unsigned int i) const - { - // Why offset from the second byte of the object? I'm not sure - return ((&reserved[2])+typeList)[i]; - } - - inline unsigned int get_types_count () const - { - return nTypes + 1; - } - - inline const ResourceRefItem &get_ref_item (const ResourceTypeItem &type, - unsigned int i) const - { - return type.get_ref_item (&(this+typeList), i); - } - - inline const PString& get_name (const ResourceRefItem &item, - unsigned int i) const - { - if (item.nameOffset == -1) - return Null (PString); - - return StructAtOffset (this, nameList + item.nameOffset); - } - - protected: - HBUINT8 reserved[16]; /* Reserved for copy of resource header */ - LOffsetTo - reserved1; /* Reserved for handle to next resource map */ - HBUINT16 reserved2; /* Reserved for file reference number */ - HBUINT16 attr; /* Resource fork attribute */ - OffsetTo > - typeList; /* Offset from beginning of map to - * resource type list */ - HBUINT16 nameList; /* Offset from beginning of map to - * resource name list */ - HBUINT16 nTypes; /* Number of types in the map minus 1 */ - public: - DEFINE_SIZE_STATIC (30); -}; - -struct ResourceForkHeader -{ - inline unsigned int get_face_count () const - { - const ResourceMap &resource_map = this+map; - for (unsigned int i = 0; i < resource_map.get_types_count (); ++i) - { - const ResourceTypeItem& type = resource_map.get_type (i); + const ResourceTypeRecord& type = get_type_record (i); if (type.is_sfnt ()) return type.get_resource_count (); } return 0; } - inline const LArrayOf& get_data (const ResourceTypeItem& type, - unsigned int idx) const + inline const OpenTypeFontFace& get_face (unsigned int idx, + const void *data_base) const { - const ResourceMap &resource_map = this+map; - unsigned int offset = dataOffset; - offset += resource_map.get_ref_item (type, idx).dataOffset; - return StructAtOffset > (this, offset); - } - - inline const OpenTypeFontFace& get_face (unsigned int idx, unsigned int *base_offset = nullptr) const - { - const ResourceMap &resource_map = this+map; - for (unsigned int i = 0; i < resource_map.get_types_count (); ++i) + unsigned int count = get_type_count (); + for (unsigned int i = 0; i < count; i++) { - const ResourceTypeItem& type = resource_map.get_type (i); + const ResourceTypeRecord& type = get_type_record (i); + /* The check for idx < count is here because ResourceRecord is NOT null-safe. + * Because an offset of 0 there does NOT mean null. */ if (type.is_sfnt () && idx < type.get_resource_count ()) - { - const OpenTypeFontFace &face = (OpenTypeFontFace&) get_data (type, idx).arrayZ; - if (base_offset) - *base_offset = (const char *) &face - (const char *) this; - return face; - } + return type.get_resource_record (idx, &(this+typeList)).get_face (data_base); } return Null (OpenTypeFontFace); } + inline bool sanitize (hb_sanitize_context_t *c, const void *data_base) const + { + TRACE_SANITIZE (this); + const void *type_base = &(this+typeList); + return_trace (c->check_struct (this) && + typeList.sanitize (c, this, + type_base, + data_base)); + } + + private: + inline unsigned int get_type_count (void) const { return (this+typeList).lenM1 + 1; } + + inline const ResourceTypeRecord& get_type_record (unsigned int i) const + { return (this+typeList)[i]; } + + protected: + HBUINT8 reserved0[16]; /* Reserved for copy of resource header */ + HBUINT32 reserved1; /* Reserved for handle to next resource map */ + HBUINT16 resreved2; /* Reserved for file reference number */ + HBUINT16 attrs; /* Resource fork attribute */ + OffsetTo > + typeList; /* Offset from beginning of map to + * resource type list */ + Offset16 nameList; /* Offset from beginning of map to + * resource name list */ + public: + DEFINE_SIZE_STATIC (28); +}; + +struct ResourceForkHeader +{ + inline unsigned int get_face_count (void) const + { return (this+map).get_face_count (); } + + inline const OpenTypeFontFace& get_face (unsigned int idx, + unsigned int *base_offset = nullptr) const + { + const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data)); + if (base_offset) + *base_offset = (const char *) &face - (const char *) this; + return face; + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) - return_trace (false); - - const ResourceMap &resource_map = this+map; - if (unlikely (!resource_map.sanitize (c))) - return_trace (false); - - for (unsigned int i = 0; i < resource_map.get_types_count (); ++i) - { - const ResourceTypeItem& type = resource_map.get_type (i); - for (unsigned int j = 0; j < type.get_resource_count (); ++j) - { - const LArrayOf& data = get_data (type, j); - if (unlikely (!(data.sanitize (c) && - ((OpenTypeFontFace&) data.arrayZ).sanitize (c)))) - return_trace (false); - } - } - - return_trace (true); + return_trace (c->check_struct (this) && + data.sanitize (c, this, dataLen) && + map.sanitize (c, this, &(this+data))); } protected: - HBUINT32 dataOffset; /* Offset from beginning of resource fork + LOffsetTo > + data; /* Offset from beginning of resource fork * to resource data */ LOffsetTo map; /* Offset from beginning of resource fork diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 5d09c5208..4f16c7d34 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -155,10 +155,10 @@ struct Index : HBUINT16 { DECLARE_NULL_NAMESPACE_BYTES (OT, Index); /* Offset, Null offset = 0 */ -template +template struct Offset : Type { - inline bool is_null (void) const { return 0 == *this; } + inline bool is_null (void) const { return has_null && 0 == *this; } inline void *serialize (hb_serialize_context_t *c, const void *base) { @@ -226,20 +226,18 @@ struct FixedVersion * Use: (base+offset) */ -template -struct OffsetTo : Offset +template +struct OffsetTo : Offset { inline const Type& operator () (const void *base) const { - unsigned int offset = *this; - if (unlikely (!offset)) return Null(Type); - return StructAtOffset (base, offset); + if (unlikely (this->is_null ())) return Null(Type); + return StructAtOffset (base, *this); } inline Type& operator () (void *base) const { - unsigned int offset = *this; - if (unlikely (!offset)) return Crap(Type); - return StructAtOffset (base, offset); + if (unlikely (this->is_null ())) return Crap(Type); + return StructAtOffset (base, *this); } inline Type& serialize (hb_serialize_context_t *c, const void *base) @@ -260,39 +258,64 @@ struct OffsetTo : Offset this->set (0); } + inline bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (this))) return_trace (false); + if (unlikely (this->is_null ())) return_trace (true); + if (unlikely (!c->check_range (base, *this))) return_trace (false); + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) return_trace (false); - unsigned int offset = *this; - if (unlikely (!offset)) return_trace (true); - if (unlikely (!c->check_range (base, offset))) return_trace (false); - const Type &obj = StructAtOffset (base, offset); - return_trace (likely (obj.sanitize (c)) || neuter (c)); + return_trace (sanitize_shallow (c, base) && + (this->is_null () || + StructAtOffset (base, *this).sanitize (c) || + neuter (c))); } - template - inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + template + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (this))) return_trace (false); - unsigned int offset = *this; - if (unlikely (!offset)) return_trace (true); - if (unlikely (!c->check_range (base, offset))) return_trace (false); - const Type &obj = StructAtOffset (base, offset); - return_trace (likely (obj.sanitize (c, user_data)) || neuter (c)); + return_trace (sanitize_shallow (c, base) && + (this->is_null () || + StructAtOffset (base, *this).sanitize (c, d1) || + neuter (c))); + } + template + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const + { + TRACE_SANITIZE (this); + return_trace (sanitize_shallow (c, base) && + (this->is_null () || + StructAtOffset (base, *this).sanitize (c, d1, d2) || + neuter (c))); + } + template + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const + { + TRACE_SANITIZE (this); + return_trace (sanitize_shallow (c, base) && + (this->is_null () || + StructAtOffset (base, *this).sanitize (c, d1, d2, d3) || + neuter (c))); } /* Set the offset to Null */ - inline bool neuter (hb_sanitize_context_t *c) const { + inline bool neuter (hb_sanitize_context_t *c) const + { + if (!has_null) return false; return c->try_set (this, 0); } DEFINE_SIZE_STATIC (sizeof(OffsetType)); }; template struct LOffsetTo : OffsetTo {}; -template -static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } -template -static inline Type& operator + (Base &base, OffsetTo &offset) { return offset (base); } +template +static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } +template +static inline Type& operator + (Base &base, OffsetTo &offset) { return offset (base); } /* @@ -547,16 +570,16 @@ struct HeadlessArrayOf { inline const Type& operator [] (unsigned int i) const { - if (unlikely (i >= len || !i)) return Null(Type); + if (unlikely (i >= lenP1 || !i)) return Null(Type); return arrayZ[i-1]; } inline Type& operator [] (unsigned int i) { - if (unlikely (i >= len || !i)) return Crap(Type); + if (unlikely (i >= lenP1 || !i)) return Crap(Type); return arrayZ[i-1]; } inline unsigned int get_size (void) const - { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } + { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; } inline bool serialize (hb_serialize_context_t *c, Supplier &items, @@ -564,7 +587,7 @@ struct HeadlessArrayOf { TRACE_SERIALIZE (this); if (unlikely (!c->extend_min (*this))) return_trace (false); - len.set (items_len); /* TODO(serialize) Overflow? */ + lenP1.set (items_len); /* TODO(serialize) Overflow? */ if (unlikely (!items_len)) return_trace (true); if (unlikely (!c->extend (*this))) return_trace (false); for (unsigned int i = 0; i < items_len - 1; i++) @@ -594,12 +617,56 @@ struct HeadlessArrayOf inline bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (len.sanitize (c) && - (!len || c->check_array (arrayZ, len - 1))); + return_trace (lenP1.sanitize (c) && + (!lenP1 || c->check_array (arrayZ, lenP1 - 1))); } public: - LenType len; + LenType lenP1; + Type arrayZ[VAR]; + public: + DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); +}; + +/* An array storing length-1. */ +template +struct ArrayOfM1 +{ + inline const Type& operator [] (unsigned int i) const + { + if (unlikely (i > lenM1)) return Null(Type); + return arrayZ[i]; + } + inline Type& operator [] (unsigned int i) + { + if (unlikely (i > lenM1)) return Crap(Type); + return arrayZ[i]; + } + inline unsigned int get_size (void) const + { return lenM1.static_size + (lenM1 + 1) * Type::static_size; } + + template + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + { + TRACE_SANITIZE (this); + if (unlikely (!sanitize_shallow (c))) return_trace (false); + unsigned int count = lenM1 + 1; + for (unsigned int i = 0; i < count; i++) + if (unlikely (!arrayZ[i].sanitize (c, base, user_data))) + return_trace (false); + return_trace (true); + } + + private: + inline bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (lenM1.sanitize (c) && + (c->check_array (arrayZ, lenM1 + 1))); + } + + public: + LenType lenM1; Type arrayZ[VAR]; public: DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 4d5db6aec..7e36e0639 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -710,7 +710,7 @@ struct Ligature { inline bool intersects (const hb_set_t *glyphs) const { - unsigned int count = component.len; + unsigned int count = component.lenP1; for (unsigned int i = 1; i < count; i++) if (!glyphs->has (component[i])) return false; @@ -720,7 +720,7 @@ struct Ligature inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); - unsigned int count = component.len; + unsigned int count = component.lenP1; for (unsigned int i = 1; i < count; i++) if (!c->glyphs->has (component[i])) return; @@ -730,14 +730,14 @@ struct Ligature inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - c->input->add_array (component.arrayZ, component.len ? component.len - 1 : 0); + c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0); c->output->add (ligGlyph); } inline bool would_apply (hb_would_apply_context_t *c) const { TRACE_WOULD_APPLY (this); - if (c->len != component.len) + if (c->len != component.lenP1) return_trace (false); for (unsigned int i = 1; i < c->len; i++) @@ -750,7 +750,7 @@ struct Ligature inline bool apply (hb_ot_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int count = component.len; + unsigned int count = component.lenP1; if (unlikely (!count)) return_trace (false); diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index eae73ce33..ff9783edc 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -1879,7 +1879,7 @@ struct ChainRule const ArrayOf &lookahead = StructAfter > (input); return chain_context_intersects (glyphs, backtrack.len, backtrack.arrayZ, - input.len, input.arrayZ, + input.lenP1, input.arrayZ, lookahead.len, lookahead.arrayZ, lookup_context); } @@ -1892,7 +1892,7 @@ struct ChainRule const ArrayOf &lookup = StructAfter > (lookahead); chain_context_closure_lookup (c, backtrack.len, backtrack.arrayZ, - input.len, input.arrayZ, + input.lenP1, input.arrayZ, lookahead.len, lookahead.arrayZ, lookup.len, lookup.arrayZ, lookup_context); @@ -1906,7 +1906,7 @@ struct ChainRule const ArrayOf &lookup = StructAfter > (lookahead); chain_context_collect_glyphs_lookup (c, backtrack.len, backtrack.arrayZ, - input.len, input.arrayZ, + input.lenP1, input.arrayZ, lookahead.len, lookahead.arrayZ, lookup.len, lookup.arrayZ, lookup_context); @@ -1920,7 +1920,7 @@ struct ChainRule const ArrayOf &lookup = StructAfter > (lookahead); return_trace (chain_context_would_apply_lookup (c, backtrack.len, backtrack.arrayZ, - input.len, input.arrayZ, + input.lenP1, input.arrayZ, lookahead.len, lookahead.arrayZ, lookup.len, lookup.arrayZ, lookup_context)); } @@ -1933,7 +1933,7 @@ struct ChainRule const ArrayOf &lookup = StructAfter > (lookahead); return_trace (chain_context_apply_lookup (c, backtrack.len, backtrack.arrayZ, - input.len, input.arrayZ, + input.lenP1, input.arrayZ, lookahead.len, lookahead.arrayZ, lookup.len, lookup.arrayZ, lookup_context)); } diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh index 29dc86fa8..5f27fd504 100644 --- a/src/hb-ot-post-table.hh +++ b/src/hb-ot-post-table.hh @@ -143,7 +143,7 @@ struct post return true; if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */ return false; - strncpy (buf, s.bytes, s.len); + strncpy (buf, s.arrayZ, s.len); buf[s.len] = '\0'; return true; }