[HB] Start sanitize()
This commit is contained in:
parent
5fc22e647c
commit
70de50c11e
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "hb-private.h"
|
||||
|
||||
#include "hb-blob.h"
|
||||
|
||||
|
||||
#define NO_INDEX ((unsigned int) 0xFFFF)
|
||||
#define NO_CONTEXT ((unsigned int) 0x110000)
|
||||
|
@ -36,6 +38,38 @@
|
|||
#define MAX_NESTING_LEVEL 8
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Sanitize
|
||||
*/
|
||||
|
||||
typedef struct _hb_sanitize_context_t hb_sanitize_context_t;
|
||||
struct _hb_sanitize_context_t
|
||||
{
|
||||
const char *start, *end;
|
||||
hb_blob_t *blob;
|
||||
};
|
||||
|
||||
#define SANITIZE_ARG_DEF \
|
||||
hb_sanitize_context_t *context
|
||||
#define SANITIZE_ARG \
|
||||
context
|
||||
|
||||
#define SANITIZE(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG))
|
||||
#define SANITIZE2(X,Y) SANITIZE (X) && SANITIZE (Y)
|
||||
|
||||
#define SANITIZE_THIS(X) HB_LIKELY ((X).sanitize (SANITIZE_ARG, (const char *) this))
|
||||
#define SANITIZE_THIS2(X,Y) SANITIZE_THIS (X) && SANITIZE_THIS (Y)
|
||||
|
||||
#define SANITIZE_SELF() SANITIZE_OBJ (*this)
|
||||
#define SANITIZE_OBJ(X) SANITIZE_MEM(&(X), sizeof (X))
|
||||
#define SANITIZE_GET_SIZE() SANITIZE_MEM (this, this->get_size ())
|
||||
|
||||
#define SANITIZE_MEM(B,L) HB_LIKELY (context->start <= (const char *)(B) && (const char *)(B) + (L) <= context->end) /* XXX overflow */
|
||||
|
||||
#define NEUTER(Var, Val) (false)
|
||||
|
||||
|
||||
/*
|
||||
* Array types
|
||||
*/
|
||||
|
@ -208,6 +242,7 @@ struct Null <Type> \
|
|||
inline NAME& operator = (TYPE i) { (TYPE&) v = BIG_ENDIAN (i); return *this; } \
|
||||
inline operator TYPE(void) const { return BIG_ENDIAN ((TYPE&) v); } \
|
||||
inline bool operator== (NAME o) const { return (TYPE&) v == (TYPE&) o.v; } \
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) { return SANITIZE_SELF (); } \
|
||||
private: char v[BYTES]; \
|
||||
}; \
|
||||
ASSERT_SIZE (NAME, BYTES)
|
||||
|
@ -257,6 +292,13 @@ struct OffsetTo : Offset
|
|||
if (HB_UNLIKELY (!offset)) return Null(Type);
|
||||
return *(const Type*)((const char *) base + offset);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
|
||||
if (!SANITIZE_OBJ (*this)) return false;
|
||||
unsigned int offset = *this;
|
||||
if (HB_UNLIKELY (!offset)) return true;
|
||||
return SANITIZE (*(Type*)((char *) base + offset)) || NEUTER (*this, 0);
|
||||
}
|
||||
};
|
||||
template <typename Base, typename Type>
|
||||
inline const Type& operator + (const Base &base, OffsetTo<Type> offset) { return offset (base); }
|
||||
|
@ -270,6 +312,13 @@ struct LongOffsetTo : LongOffset
|
|||
if (HB_UNLIKELY (!offset)) return Null(Type);
|
||||
return *(const Type*)((const char *) base + offset);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
|
||||
if (!SANITIZE (*this)) return false;
|
||||
unsigned int offset = *this;
|
||||
if (HB_UNLIKELY (!offset)) return true;
|
||||
return SANITIZE (*(Type*)((char *) base + offset)) || NEUTER (*this, 0);
|
||||
}
|
||||
};
|
||||
template <typename Base, typename Type>
|
||||
inline const Type& operator + (const Base &base, LongOffsetTo<Type> offset) { return offset (base); }
|
||||
|
@ -320,6 +369,16 @@ struct ArrayOf
|
|||
inline unsigned int get_size () const
|
||||
{ return sizeof (len) + len * sizeof (array[0]); }
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!(SANITIZE (len) && SANITIZE_GET_SIZE())) return false;
|
||||
/* For non-offset types, this shouldn't be needed
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!SANITIZE (array[i]))
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
USHORT len;
|
||||
Type array[];
|
||||
};
|
||||
|
@ -337,6 +396,14 @@ struct HeadlessArrayOf
|
|||
inline unsigned int get_size () const
|
||||
{ return sizeof (len) + (len ? len - 1 : 0) * sizeof (array[0]); }
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!(SANITIZE_SELF () && SANITIZE_GET_SIZE())) return false;
|
||||
unsigned int count = len ? len - 1 : 0;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!SANITIZE (array[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
USHORT len;
|
||||
Type array[];
|
||||
};
|
||||
|
@ -353,21 +420,53 @@ struct LongArrayOf
|
|||
inline unsigned int get_size () const
|
||||
{ return sizeof (len) + len * sizeof (array[0]); }
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!(SANITIZE_SELF () && SANITIZE_GET_SIZE())) return false;
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!SANITIZE (array[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
ULONG len;
|
||||
Type array[];
|
||||
};
|
||||
|
||||
/* Array of Offset's */
|
||||
template <typename Type>
|
||||
struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {};
|
||||
struct OffsetArrayOf : ArrayOf<OffsetTo<Type> > {
|
||||
inline bool sanitize (SANITIZE_ARG_DEF, const char *base) {
|
||||
if (!(SANITIZE (this->len) && SANITIZE_GET_SIZE())) return false;
|
||||
unsigned int count = this->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!this->array[i].sanitize (SANITIZE_ARG, base))
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/* Array of LongOffset's */
|
||||
template <typename Type>
|
||||
struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {};
|
||||
struct LongOffsetArrayOf : ArrayOf<LongOffsetTo<Type> > {
|
||||
inline bool sanitize (SANITIZE_ARG_DEF, const char *base) {
|
||||
if (!(SANITIZE (this->len) && SANITIZE_GET_SIZE())) return false;
|
||||
unsigned int count = this->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!this->array[i].sanitize (SANITIZE_ARG, base))
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/* LongArray of LongOffset's */
|
||||
template <typename Type>
|
||||
struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {};
|
||||
struct LongOffsetLongArrayOf : LongArrayOf<LongOffsetTo<Type> > {
|
||||
inline bool sanitize (SANITIZE_ARG_DEF, const char *base) {
|
||||
if (!(SANITIZE (this->len) && SANITIZE_GET_SIZE())) return false;
|
||||
unsigned int count = this->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!this->array[i].sanitize (SANITIZE_ARG, base))
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/* An array type is one that contains a variable number of objects
|
||||
* as its last item. An array object is extended with get_len()
|
||||
|
|
|
@ -239,6 +239,11 @@ struct CoverageFormat1
|
|||
return NOT_COVERED;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE (glyphArray);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT coverageFormat; /* Format identifier--format = 1 */
|
||||
ArrayOf<GlyphID>
|
||||
glyphArray; /* Array of GlyphIDs--in numerical order */
|
||||
|
@ -257,6 +262,10 @@ struct CoverageRangeRecord
|
|||
return NOT_COVERED;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_SELF ();
|
||||
}
|
||||
|
||||
private:
|
||||
GlyphID start; /* First GlyphID in the range */
|
||||
GlyphID end; /* Last GlyphID in the range */
|
||||
|
@ -283,6 +292,11 @@ struct CoverageFormat2
|
|||
return NOT_COVERED;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE (rangeRecord);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT coverageFormat; /* Format identifier--format = 2 */
|
||||
ArrayOf<CoverageRangeRecord>
|
||||
rangeRecord; /* Array of glyph ranges--ordered by
|
||||
|
@ -293,6 +307,8 @@ ASSERT_SIZE (CoverageFormat2, 4);
|
|||
|
||||
struct Coverage
|
||||
{
|
||||
inline unsigned int operator() (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); }
|
||||
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
switch (u.format) {
|
||||
|
@ -302,7 +318,14 @@ struct Coverage
|
|||
}
|
||||
}
|
||||
|
||||
inline unsigned int operator() (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); }
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
case 2: return u.format2->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
|
@ -330,6 +353,10 @@ struct ClassDefFormat1
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_SELF () && SANITIZE (classValue);
|
||||
}
|
||||
|
||||
USHORT classFormat; /* Format identifier--format = 1 */
|
||||
GlyphID startGlyph; /* First GlyphID of the classValueArray */
|
||||
ArrayOf<USHORT>
|
||||
|
@ -349,6 +376,10 @@ struct ClassRangeRecord
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_SELF ();
|
||||
}
|
||||
|
||||
private:
|
||||
GlyphID start; /* First GlyphID in the range */
|
||||
GlyphID end; /* Last GlyphID in the range */
|
||||
|
@ -374,6 +405,10 @@ struct ClassDefFormat2
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE (rangeRecord);
|
||||
}
|
||||
|
||||
USHORT classFormat; /* Format identifier--format = 2 */
|
||||
ArrayOf<ClassRangeRecord>
|
||||
rangeRecord; /* Array of glyph ranges--ordered by
|
||||
|
@ -383,6 +418,8 @@ ASSERT_SIZE (ClassDefFormat2, 4);
|
|||
|
||||
struct ClassDef
|
||||
{
|
||||
inline unsigned int operator() (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
|
||||
|
||||
hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
switch (u.format) {
|
||||
|
@ -392,7 +429,14 @@ struct ClassDef
|
|||
}
|
||||
}
|
||||
|
||||
inline unsigned int operator() (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
case 2: return u.format2->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
|
|
|
@ -35,6 +35,7 @@ struct SingleSubstFormat1
|
|||
friend struct SingleSubst;
|
||||
|
||||
private:
|
||||
|
||||
inline bool apply (APPLY_ARG_DEF) const
|
||||
{
|
||||
hb_codepoint_t glyph_id = IN_CURGLYPH ();
|
||||
|
@ -52,6 +53,10 @@ struct SingleSubstFormat1
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS (coverage) && SANITIZE (deltaGlyphID);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -67,6 +72,7 @@ struct SingleSubstFormat2
|
|||
friend struct SingleSubst;
|
||||
|
||||
private:
|
||||
|
||||
inline bool apply (APPLY_ARG_DEF) const
|
||||
{
|
||||
hb_codepoint_t glyph_id = IN_CURGLYPH ();
|
||||
|
@ -87,6 +93,10 @@ struct SingleSubstFormat2
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS (coverage) && SANITIZE (substitute);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 2 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -103,6 +113,7 @@ struct SingleSubst
|
|||
friend struct SubstLookupSubTable;
|
||||
|
||||
private:
|
||||
|
||||
inline bool apply (APPLY_ARG_DEF) const
|
||||
{
|
||||
switch (u.format) {
|
||||
|
@ -112,6 +123,15 @@ struct SingleSubst
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
case 2: return u.format2->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
|
@ -150,6 +170,11 @@ struct Sequence
|
|||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE (substitute);
|
||||
}
|
||||
|
||||
private:
|
||||
ArrayOf<GlyphID>
|
||||
substitute; /* String of GlyphIDs to substitute */
|
||||
|
@ -161,6 +186,7 @@ struct MultipleSubstFormat1
|
|||
friend struct MultipleSubst;
|
||||
|
||||
private:
|
||||
|
||||
inline bool apply (APPLY_ARG_DEF) const
|
||||
{
|
||||
|
||||
|
@ -171,6 +197,10 @@ struct MultipleSubstFormat1
|
|||
return (this+sequence[index]).apply (APPLY_ARG);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS2 (coverage, sequence);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -187,6 +217,7 @@ struct MultipleSubst
|
|||
friend struct SubstLookupSubTable;
|
||||
|
||||
private:
|
||||
|
||||
inline bool apply (APPLY_ARG_DEF) const
|
||||
{
|
||||
switch (u.format) {
|
||||
|
@ -195,6 +226,14 @@ struct MultipleSubst
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
|
@ -213,6 +252,7 @@ struct AlternateSubstFormat1
|
|||
friend struct AlternateSubst;
|
||||
|
||||
private:
|
||||
|
||||
inline bool apply (APPLY_ARG_DEF) const
|
||||
{
|
||||
hb_codepoint_t glyph_id = IN_CURGLYPH ();
|
||||
|
@ -249,6 +289,10 @@ struct AlternateSubstFormat1
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS2 (coverage, alternateSet);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -265,6 +309,7 @@ struct AlternateSubst
|
|||
friend struct SubstLookupSubTable;
|
||||
|
||||
private:
|
||||
|
||||
inline bool apply (APPLY_ARG_DEF) const
|
||||
{
|
||||
switch (u.format) {
|
||||
|
@ -273,6 +318,14 @@ struct AlternateSubst
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
|
@ -352,6 +405,11 @@ struct Ligature
|
|||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE2 (ligGlyph, component);
|
||||
}
|
||||
|
||||
private:
|
||||
GlyphID ligGlyph; /* GlyphID of ligature to substitute */
|
||||
HeadlessArrayOf<GlyphID>
|
||||
|
@ -379,6 +437,11 @@ struct LigatureSet
|
|||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS (ligature);
|
||||
}
|
||||
|
||||
private:
|
||||
OffsetArrayOf<Ligature>
|
||||
ligature; /* Array LigatureSet tables
|
||||
|
@ -405,6 +468,10 @@ struct LigatureSubstFormat1
|
|||
return lig_set.apply (APPLY_ARG, first_is_mark);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS2 (coverage, ligatureSet);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -429,6 +496,14 @@ struct LigatureSubst
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
|
@ -467,7 +542,14 @@ struct ExtensionSubst : Extension
|
|||
friend struct SubstLookupSubTable;
|
||||
|
||||
private:
|
||||
inline const struct SubstLookupSubTable& get_subtable (void) const
|
||||
{ return (const struct SubstLookupSubTable&) Extension::get_subtable (); }
|
||||
inline struct SubstLookupSubTable& get_subtable (void)
|
||||
{ return (struct SubstLookupSubTable&) Extension::get_subtable (); }
|
||||
|
||||
inline bool apply (APPLY_ARG_DEF) const;
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF);
|
||||
};
|
||||
ASSERT_SIZE (ExtensionSubst, 2);
|
||||
|
||||
|
@ -507,6 +589,19 @@ struct ReverseChainSingleSubstFormat1
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE_THIS2 (coverage, backtrack))
|
||||
return false;
|
||||
OffsetArrayOf<Coverage> &lookahead = (OffsetArrayOf<Coverage>&)
|
||||
*((const char *) &backtrack + backtrack.get_size ());
|
||||
if (!SANITIZE_THIS (lookahead))
|
||||
return false;
|
||||
ArrayOf<GlyphID> &substitute = (ArrayOf<GlyphID>&)
|
||||
*((const char *) &lookahead + lookahead.get_size ());
|
||||
if (!SANITIZE (substitute))
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -539,6 +634,14 @@ struct ReverseChainSingleSubst
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
|
@ -583,6 +686,21 @@ struct SubstLookupSubTable
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case Single: return u.single->sanitize (SANITIZE_ARG);
|
||||
case Multiple: return u.multiple->sanitize (SANITIZE_ARG);
|
||||
case Alternate: return u.alternate->sanitize (SANITIZE_ARG);
|
||||
case Ligature: return u.ligature->sanitize (SANITIZE_ARG);
|
||||
case Context: return u.context->sanitize (SANITIZE_ARG);
|
||||
case ChainContext: return u.chainContext->sanitize (SANITIZE_ARG);
|
||||
case Extension: return u.extension->sanitize (SANITIZE_ARG);
|
||||
case ReverseChainSingle: return u.reverseChainContextSingle->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format;
|
||||
|
@ -729,7 +847,12 @@ inline bool ExtensionSubst::apply (APPLY_ARG_DEF) const
|
|||
if (HB_UNLIKELY (lookup_type == SubstLookupSubTable::Extension))
|
||||
return false;
|
||||
|
||||
return ((SubstLookupSubTable&) get_subtable ()).apply (APPLY_ARG, lookup_type);
|
||||
return get_subtable ().apply (APPLY_ARG, lookup_type);
|
||||
}
|
||||
|
||||
inline bool ExtensionSubst::sanitize (SANITIZE_ARG_DEF)
|
||||
{
|
||||
return Extension::sanitize (SANITIZE_ARG) && get_subtable ().sanitize (SANITIZE_ARG);
|
||||
}
|
||||
|
||||
static inline bool substitute_lookup (APPLY_ARG_DEF, unsigned int lookup_index)
|
||||
|
|
|
@ -260,6 +260,14 @@ struct Rule
|
|||
lookup_context);
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE_SELF ()) return false;
|
||||
return SANITIZE_MEM (input,
|
||||
sizeof (input[0]) * inputCount +
|
||||
sizeof (lookupRecordX[0]) * lookupCount);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT inputCount; /* Total number of glyphs in input
|
||||
* glyph sequence--includes the first
|
||||
|
@ -286,6 +294,10 @@ struct RuleSet
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS (rule);
|
||||
}
|
||||
|
||||
private:
|
||||
OffsetArrayOf<Rule>
|
||||
rule; /* Array of Rule tables
|
||||
|
@ -312,6 +324,10 @@ struct ContextFormat1
|
|||
return rule_set.apply (APPLY_ARG, lookup_context);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS2 (coverage, ruleSet);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -348,6 +364,10 @@ struct ContextFormat2
|
|||
return rule_set.apply (APPLY_ARG, lookup_context);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS2 (coverage, classDef) && SANITIZE_THIS (ruleSet);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 2 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -387,6 +407,17 @@ struct ContextFormat3
|
|||
lookup_context);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE_SELF ()) return false;
|
||||
unsigned int count = glyphCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!SANITIZE_THIS (coverage[i])) return false;
|
||||
LookupRecord *lookupRecord = (LookupRecord *)
|
||||
((char *) coverage +
|
||||
sizeof (coverage[0]) * glyphCount);
|
||||
return SANITIZE_MEM (lookupRecord, sizeof (lookupRecord[0]) * lookupCount);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 3 */
|
||||
USHORT glyphCount; /* Number of glyphs in the input glyph
|
||||
|
@ -413,6 +444,16 @@ struct Context
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
case 2: return u.format2->sanitize (SANITIZE_ARG);
|
||||
case 3: return u.format3->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
|
@ -490,6 +531,19 @@ struct ChainRule
|
|||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (backtrack)) return false;
|
||||
HeadlessArrayOf<USHORT> &input = *(HeadlessArrayOf<USHORT>*)
|
||||
((char *) &backtrack + backtrack.get_size ());
|
||||
if (!SANITIZE (input)) return false;
|
||||
ArrayOf<USHORT> &lookahead = *(ArrayOf<USHORT>*)
|
||||
((char *) &input + input.get_size ());
|
||||
if (!SANITIZE (lookahead)) return false;
|
||||
ArrayOf<LookupRecord> &lookup = *(ArrayOf<LookupRecord>*)
|
||||
((char *) &lookahead + lookahead.get_size ());
|
||||
return SANITIZE (lookup);
|
||||
}
|
||||
|
||||
private:
|
||||
ArrayOf<USHORT>
|
||||
|
@ -522,6 +576,10 @@ struct ChainRuleSet
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS (rule);
|
||||
}
|
||||
|
||||
private:
|
||||
OffsetArrayOf<ChainRule>
|
||||
rule; /* Array of ChainRule tables
|
||||
|
@ -547,6 +605,11 @@ struct ChainContextFormat1
|
|||
};
|
||||
return rule_set.apply (APPLY_ARG, lookup_context);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS2 (coverage, ruleSet);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 1 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -587,6 +650,12 @@ struct ChainContextFormat2
|
|||
return rule_set.apply (APPLY_ARG, lookup_context);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_THIS2 (coverage, backtrackClassDef) &&
|
||||
SANITIZE_THIS2 (inputClassDef, lookaheadClassDef) &&
|
||||
SANITIZE_THIS (ruleSet);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 2 */
|
||||
OffsetTo<Coverage>
|
||||
|
@ -642,6 +711,19 @@ struct ChainContextFormat3
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE_THIS (backtrack)) return false;
|
||||
OffsetArrayOf<Coverage> &input = *(OffsetArrayOf<Coverage>*)
|
||||
((char *) &backtrack + backtrack.get_size ());
|
||||
if (!SANITIZE_THIS (input)) return false;
|
||||
OffsetArrayOf<Coverage> &lookahead = *(OffsetArrayOf<Coverage>*)
|
||||
((char *) &input + input.get_size ());
|
||||
if (!SANITIZE_THIS (lookahead)) return false;
|
||||
ArrayOf<LookupRecord> &lookup = *(ArrayOf<LookupRecord>*)
|
||||
((char *) &lookahead + lookahead.get_size ());
|
||||
return SANITIZE (lookup);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier--format = 3 */
|
||||
OffsetArrayOf<Coverage>
|
||||
|
@ -675,6 +757,16 @@ struct ChainContext
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
case 2: return u.format2->sanitize (SANITIZE_ARG);
|
||||
case 3: return u.format3->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
|
@ -700,6 +792,10 @@ struct ExtensionFormat1
|
|||
return *(LookupSubTable*)(((char *) this) + offset);
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
return SANITIZE_SELF ();
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format; /* Format identifier. Set to 1. */
|
||||
USHORT extensionLookupType; /* Lookup type of subtable referenced
|
||||
|
@ -729,6 +825,14 @@ struct Extension
|
|||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (SANITIZE_ARG_DEF) {
|
||||
if (!SANITIZE (u.format)) return false;
|
||||
switch (u.format) {
|
||||
case 1: return u.format1->sanitize (SANITIZE_ARG);
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
USHORT format; /* Format identifier */
|
||||
|
|
Loading…
Reference in New Issue