Merge branch 'master' into cff-subset

This commit is contained in:
Michiharu Ariza 2018-09-13 12:44:00 -07:00
commit f2c4720ae6
6 changed files with 224 additions and 182 deletions

View File

@ -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 <typename T>
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;
};

View File

@ -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<OpenTypeFontFace> ((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<LArrayOf<HBUINT8>, 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<ResourceRecord> ((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<UnsizedArrayOf<ResourceRefItem> >
refList; /* Offset from beginning of resource type list
Tag tag; /* Resource type. */
HBUINT16 resCountM1; /* Number of resources minus 1. */
OffsetTo<UnsizedArrayOf<ResourceRecord> >
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<PString> (this, nameList + item.nameOffset);
}
protected:
HBUINT8 reserved[16]; /* Reserved for copy of resource header */
LOffsetTo<ResourceMap>
reserved1; /* Reserved for handle to next resource map */
HBUINT16 reserved2; /* Reserved for file reference number */
HBUINT16 attr; /* Resource fork attribute */
OffsetTo<UnsizedArrayOf<ResourceTypeItem> >
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<HBUINT8>& 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<LArrayOf<HBUINT8> > (this, offset);
unsigned int count = get_type_count ();
for (unsigned int i = 0; i < count; 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 ())
return type.get_resource_record (idx, &(this+typeList)).get_face (data_base);
}
return Null (OpenTypeFontFace);
}
inline const OpenTypeFontFace& get_face (unsigned int idx, unsigned int *base_offset = nullptr) const
inline bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
{
const ResourceMap &resource_map = this+map;
for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
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<ArrayOfM1<ResourceTypeRecord> >
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
{
const ResourceTypeItem& type = resource_map.get_type (i);
if (type.is_sfnt () && idx < type.get_resource_count ())
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 = (OpenTypeFontFace&) get_data (type, idx).arrayZ;
const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data));
if (base_offset)
*base_offset = (const char *) &face - (const char *) this;
return face;
}
}
return Null (OpenTypeFontFace);
}
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<HBUINT8>& 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<UnsizedArrayOf<HBUINT8> >
data; /* Offset from beginning of resource fork
* to resource data */
LOffsetTo<ResourceMap>
map; /* Offset from beginning of resource fork

View File

@ -155,10 +155,10 @@ struct Index : HBUINT16 {
DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
/* Offset, Null offset = 0 */
template <typename Type>
template <typename Type, bool has_null=true>
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 <typename Type, typename OffsetType=HBUINT16>
struct OffsetTo : Offset<OffsetType>
template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
struct OffsetTo : Offset<OffsetType, has_null>
{
inline const Type& operator () (const void *base) const
{
unsigned int offset = *this;
if (unlikely (!offset)) return Null(Type);
return StructAtOffset<const Type> (base, offset);
if (unlikely (this->is_null ())) return Null(Type);
return StructAtOffset<const Type> (base, *this);
}
inline Type& operator () (void *base) const
{
unsigned int offset = *this;
if (unlikely (!offset)) return Crap(Type);
return StructAtOffset<Type> (base, offset);
if (unlikely (this->is_null ())) return Crap(Type);
return StructAtOffset<Type> (base, *this);
}
inline Type& serialize (hb_serialize_context_t *c, const void *base)
@ -260,39 +258,64 @@ struct OffsetTo : Offset<OffsetType>
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<Type> (base, offset);
return_trace (likely (obj.sanitize (c)) || neuter (c));
return_trace (sanitize_shallow (c, base) &&
(this->is_null () ||
StructAtOffset<Type> (base, *this).sanitize (c) ||
neuter (c)));
}
template <typename T>
inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
template <typename T1>
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<Type> (base, offset);
return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
return_trace (sanitize_shallow (c, base) &&
(this->is_null () ||
StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
neuter (c)));
}
template <typename T1, typename T2>
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<Type> (base, *this).sanitize (c, d1, d2) ||
neuter (c)));
}
template <typename T1, typename T2, typename T3>
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<Type> (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 <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
template <typename Base, typename OffsetType, typename Type>
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
template <typename Base, typename OffsetType, typename Type>
static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
template <typename Base, typename OffsetType, bool has_null, typename Type>
static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
template <typename Base, typename OffsetType, bool has_null, typename Type>
static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &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<Type> &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 <typename Type, typename LenType=HBUINT16>
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 <typename T>
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);

View File

@ -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);

View File

@ -1879,7 +1879,7 @@ struct ChainRule
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (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<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (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<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (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<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (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<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (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));
}

View File

@ -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;
}