[dfont] Solve the mystery +2 offset thing!

Previously, ResourceForkHeader was defined as 30 bytes, having the typeCountM1 as last member.
There was a mysterious offset-by-2 in the code, derived from FontTools and JDK code this was
ported from.

In testing, I observed that typeListZ offset is actually 28.  Suggesting that the typeCountM1
does NOT actually belong to ResourceForkHeader, but belongs to the array itself.  Adjusting for
that resolves the mystery +2 offset hack, so everything is clean and good now.

This, concludes my dfont hacking.  The code looks great now, and I'm happy to leave it.
Fuzzers might disagree though, we will see!
This commit is contained in:
Behdad Esfahbod 2018-09-13 20:30:04 +02:00
parent effc7ced72
commit 3789c557ca
2 changed files with 56 additions and 18 deletions

View File

@ -357,13 +357,6 @@ struct ResourceTypeRecord
struct ResourceMap
{
inline const ResourceTypeRecord& get_type_record (unsigned int i) const
{
// Why offset from the third byte of the object? I'm not sure
return hb_array_t<ResourceTypeRecord> (((2 + (const char *) this )+typeListZ).arrayZ,
get_type_count ()) [i];
}
inline unsigned int get_face_count (void) const
{
unsigned int count = get_type_count ();
@ -386,7 +379,7 @@ struct ResourceMap
/* 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+typeListZ)).get_face (data_base);
return type.get_resource_record (idx, &(this+typeList)).get_face (data_base);
}
return Null (OpenTypeFontFace);
}
@ -394,30 +387,31 @@ struct ResourceMap
inline bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
{
TRACE_SANITIZE (this);
const void *type_base = &(this+typeListZ);
const void *type_base = &(this+typeList);
return_trace (c->check_struct (this) &&
typeListZ.sanitize (c, 2 + (const char *) this,
get_type_count (),
type_base,
data_base));
typeList.sanitize (c, this,
type_base,
data_base));
}
private:
inline unsigned int get_type_count (void) const { return typeCountM1 + 1; }
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<UnsizedArrayOf<ResourceTypeRecord> >
typeListZ; /* Offset from beginning of map to
OffsetTo<ArrayOfM1<ResourceTypeRecord> >
typeList; /* Offset from beginning of map to
* resource type list */
Offset16 nameList; /* Offset from beginning of map to
* resource name list */
HBUINT16 typeCountM1; /* Number of types in the map minus 1 */
public:
DEFINE_SIZE_STATIC (30);
DEFINE_SIZE_STATIC (28);
};
struct ResourceForkHeader

View File

@ -628,6 +628,50 @@ struct HeadlessArrayOf
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);
};
/* An array with sorted elements. Supports binary searching. */
template <typename Type, typename LenType=HBUINT16>
struct SortedArrayOf : ArrayOf<Type, LenType>