[pango/harfbuzz-ng: 36/57] [HB] Start sanitize()



commit dc6fe7c38db8c74453770d74961e708722d7621e
Author: Behdad Esfahbod <behdad behdad org>
Date:   Tue Aug 4 00:58:28 2009 -0400

    [HB] Start sanitize()

 pango/opentype/hb-open-types-private.hh         |  105 ++++++++++++++++++-
 pango/opentype/hb-ot-layout-common-private.hh   |   48 ++++++++-
 pango/opentype/hb-ot-layout-gsub-private.hh     |  125 ++++++++++++++++++++++-
 pango/opentype/hb-ot-layout-gsubgpos-private.hh |  104 +++++++++++++++++++
 4 files changed, 376 insertions(+), 6 deletions(-)
---
diff --git a/pango/opentype/hb-open-types-private.hh b/pango/opentype/hb-open-types-private.hh
index 98efde4..a8549e2 100644
--- a/pango/opentype/hb-open-types-private.hh
+++ b/pango/opentype/hb-open-types-private.hh
@@ -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()
diff --git a/pango/opentype/hb-ot-layout-common-private.hh b/pango/opentype/hb-ot-layout-common-private.hh
index 8f24fad..3eb0a55 100644
--- a/pango/opentype/hb-ot-layout-common-private.hh
+++ b/pango/opentype/hb-ot-layout-common-private.hh
@@ -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 {
diff --git a/pango/opentype/hb-ot-layout-gsub-private.hh b/pango/opentype/hb-ot-layout-gsub-private.hh
index 37cc00b..af58a1f 100644
--- a/pango/opentype/hb-ot-layout-gsub-private.hh
+++ b/pango/opentype/hb-ot-layout-gsub-private.hh
@@ -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)
diff --git a/pango/opentype/hb-ot-layout-gsubgpos-private.hh b/pango/opentype/hb-ot-layout-gsubgpos-private.hh
index 13f9dba..a14166c 100644
--- a/pango/opentype/hb-ot-layout-gsubgpos-private.hh
+++ b/pango/opentype/hb-ot-layout-gsubgpos-private.hh
@@ -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 */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]