[HarfBuzz] harfbuzz-ng: Branch 'master' - 19 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Apr 22 18:28:30 PDT 2010


 src/hb-open-file-private.hh          |   37 ++++-----------
 src/hb-open-type-private.hh          |   68 +++++++++++++++-------------
 src/hb-ot-layout-common-private.hh   |   30 +++---------
 src/hb-ot-layout-gdef-private.hh     |    2 
 src/hb-ot-layout-gpos-private.hh     |   76 +++++++++++---------------------
 src/hb-ot-layout-gsub-private.hh     |   83 ++++++++++++++++++++---------------
 src/hb-ot-layout-gsubgpos-private.hh |   30 +++++-------
 src/main.cc                          |    4 -
 8 files changed, 148 insertions(+), 182 deletions(-)

New commits:
commit a065f471b3bc23d33ef75217308efeaed4ffd033
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 20:15:11 2010 -0400

    Cleanup Extension lookups
    
    Two things:
    
    1. Allow nested Extension lookups.  The offset is always positive, so
    it can't loop circularly.
    
    2. Move the check for all Extension subtables having the same lookup
    type to the correct place.  Before it wasn't really working.

diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index c8b2b33..65937fb 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -1447,26 +1447,6 @@ struct PosLookup : Lookup
   inline const PosLookupSubTable& get_subtable (unsigned int i) const
   { return this+Cast<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
 
-  /* Like get_type(), but looks through extension lookups.
-   * Never returns Extension */
-  inline unsigned int get_effective_type (void) const
-  {
-    unsigned int type = get_type ();
-
-    if (HB_UNLIKELY (type == PosLookupSubTable::Extension))
-    {
-      unsigned int count = get_subtable_count ();
-      type = get_subtable(0).u.extension->get_type ();
-      /* The spec says all subtables should have the same type.
-       * This is specially important if one has a reverse type! */
-      for (unsigned int i = 1; i < count; i++)
-        if (get_subtable(i).u.extension->get_type () != type)
-	  return 0;
-    }
-
-    return type;
-  }
-
   inline bool apply_once (hb_ot_layout_context_t *context,
 			  hb_buffer_t    *buffer,
 			  unsigned int    context_length,
@@ -1567,20 +1547,13 @@ ASSERT_SIZE (GPOS, 10);
 inline bool ExtensionPos::apply (APPLY_ARG_DEF) const
 {
   TRACE_APPLY ();
-  unsigned int lookup_type = get_type ();
-
-  if (HB_UNLIKELY (lookup_type == PosLookupSubTable::Extension))
-    return false;
-
-  return get_subtable ().apply (APPLY_ARG, lookup_type);
+  return get_subtable ().apply (APPLY_ARG, get_type ());
 }
 
 inline bool ExtensionPos::sanitize (SANITIZE_ARG_DEF)
 {
   TRACE_SANITIZE ();
   if (HB_UNLIKELY (!Extension::sanitize (SANITIZE_ARG))) return false;
-  if (HB_UNLIKELY (get_type () == PosLookupSubTable::Extension)) return false;
-
   unsigned int offset = get_offset ();
   if (HB_UNLIKELY (!offset)) return true;
   return SANITIZE (StructAtOffset<PosLookupSubTable> (*this, offset));
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index fd44575..0d6bbc9 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -560,6 +560,7 @@ struct ChainContextSubst : ChainContext
 struct ExtensionSubst : Extension
 {
   friend struct SubstLookupSubTable;
+  friend struct SubstLookup;
 
   private:
   inline const struct SubstLookupSubTable& get_subtable (void) const
@@ -572,6 +573,8 @@ struct ExtensionSubst : Extension
   inline bool apply (APPLY_ARG_DEF) const;
 
   inline bool sanitize (SANITIZE_ARG_DEF);
+
+  inline bool is_reverse (void) const;
 };
 
 
@@ -742,28 +745,17 @@ struct SubstLookup : Lookup
   inline const SubstLookupSubTable& get_subtable (unsigned int i) const
   { return this+Cast<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; }
 
-  /* Like get_type(), but looks through extension lookups.
-   * Never returns Extension */
-  inline unsigned int get_effective_type (void) const
+  inline static bool lookup_type_is_reverse (unsigned int lookup_type)
+  { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
+
+  inline bool is_reverse (void) const
   {
     unsigned int type = get_type ();
-
     if (HB_UNLIKELY (type == SubstLookupSubTable::Extension))
-    {
-      unsigned int count = get_subtable_count ();
-      type = get_subtable(0).u.extension->get_type ();
-      /* The spec says all subtables should have the same type.
-       * This is specially important if one has a reverse type! */
-      for (unsigned int i = 1; i < count; i++)
-        if (get_subtable(i).u.extension->get_type () != type)
-	  return 0;
-    }
-
-    return type;
+      return Cast<ExtensionSubst> (get_subtable(0)).is_reverse ();
+    return lookup_type_is_reverse (type);
   }
 
-  inline bool is_reverse (void) const
-  { return HB_UNLIKELY (get_effective_type () == SubstLookupSubTable::ReverseChainSingle); }
 
   inline bool apply_once (hb_ot_layout_context_t *context,
 			  hb_buffer_t    *buffer,
@@ -777,6 +769,20 @@ struct SubstLookup : Lookup
     if (!_hb_ot_layout_check_glyph_property (context->face, IN_CURINFO (), lookup_flag, &property))
       return false;
 
+    if (HB_UNLIKELY (lookup_type == SubstLookupSubTable::Extension))
+    {
+      /* The spec says all subtables should have the same type.
+       * This is specially important if one has a reverse type!
+       *
+       * This is rather slow to do this here for every glyph,
+       * but it's easiest, and who uses extension lookups anyway?!*/
+      unsigned int count = get_subtable_count ();
+      unsigned int type = get_subtable(0).u.extension->get_type ();
+      for (unsigned int i = 1; i < count; i++)
+        if (get_subtable(i).u.extension->get_type () != type)
+	  return false;
+    }
+
     unsigned int count = get_subtable_count ();
     for (unsigned int i = 0; i < count; i++)
       if (get_subtable (i).apply (APPLY_ARG_INIT, lookup_type))
@@ -877,25 +883,26 @@ ASSERT_SIZE (GSUB, 10);
 inline bool ExtensionSubst::apply (APPLY_ARG_DEF) const
 {
   TRACE_APPLY ();
-  unsigned int lookup_type = get_type ();
-
-  if (HB_UNLIKELY (lookup_type == SubstLookupSubTable::Extension))
-    return false;
-
-  return get_subtable ().apply (APPLY_ARG, lookup_type);
+  return get_subtable ().apply (APPLY_ARG, get_type ());
 }
 
 inline bool ExtensionSubst::sanitize (SANITIZE_ARG_DEF)
 {
   TRACE_SANITIZE ();
   if (HB_UNLIKELY (!Extension::sanitize (SANITIZE_ARG))) return false;
-  if (HB_UNLIKELY (get_type () == SubstLookupSubTable::Extension)) return false;
-
   unsigned int offset = get_offset ();
   if (HB_UNLIKELY (!offset)) return true;
   return SANITIZE (StructAtOffset<SubstLookupSubTable> (*this, offset));
 }
 
+inline bool ExtensionSubst::is_reverse (void) const
+{
+  unsigned int type = get_type ();
+  if (HB_UNLIKELY (type == SubstLookupSubTable::Extension))
+    return Cast<ExtensionSubst> (get_subtable()).is_reverse ();
+  return SubstLookup::lookup_type_is_reverse (type);
+}
+
 static inline bool substitute_lookup (APPLY_ARG_DEF, unsigned int lookup_index)
 {
   const GSUB &gsub = *(context->face->ot_layout.gsub);
commit a0bb49c5830f8a7f25d573ec57b79df2620ddba7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 18:47:03 2010 -0400

    Add comment re bsearch effect on sanitize

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 605d75c..2e70b96 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -85,7 +85,7 @@ typedef struct OffsetTable
   {
     Tag t;
     t.set (tag);
-    // TODO bsearch
+    // TODO: bsearch (need to sort in sanitize)
     unsigned int count = numTables;
     for (unsigned int i = 0; i < count; i++)
     {
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index cfbca1d..2315df9 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -87,7 +87,7 @@ struct RecordArrayOf : ArrayOf<Record<Type> > {
   {
     Tag t;
     t.set (tag);
-    // TODO bsearch
+    // TODO: bsearch (need to sort in sanitize)
     const Record<Type> *a = this->array();
     unsigned int count = this->len;
     for (unsigned int i = 0; i < count; i++)
@@ -321,7 +321,7 @@ struct CoverageFormat1
       return NOT_COVERED;
     GlyphID gid;
     gid.set (glyph_id);
-    // TODO: bsearch
+    // TODO: bsearch (need to sort in sanitize)
     unsigned int num_glyphs = glyphArray.len;
     for (unsigned int i = 0; i < num_glyphs; i++)
       if (gid == glyphArray[i])
@@ -377,7 +377,7 @@ struct CoverageFormat2
   private:
   inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
   {
-    // TODO: bsearch
+    // TODO: bsearch (need to sort in sanitize)
     unsigned int count = rangeRecord.len;
     for (unsigned int i = 0; i < count; i++)
     {
@@ -497,7 +497,7 @@ struct ClassDefFormat2
   private:
   inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
   {
-    // TODO: bsearch
+    // TODO: bsearch (need to sort in sanitize)
     unsigned int count = rangeRecord.len;
     for (unsigned int i = 0; i < count; i++)
     {
commit d632ec4000b3079150e6424e88a3ab7509f7445c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 18:33:12 2010 -0400

    Cosmetic

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 2ef124a..3a89425 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -61,10 +61,10 @@ inline Type& Cast(TObject &X)
  * location of X plus Ofs bytes. */
 template<typename Type, typename TObject>
 inline const Type& StructAtOffset(const TObject &X, unsigned int offset)
-{ return * reinterpret_cast<const Type*> (CharP (&X) + offset); }
+{ return * reinterpret_cast<const Type*> (CharP(&X) + offset); }
 template<typename Type, typename TObject>
 inline Type& StructAtOffset(TObject &X, unsigned int offset)
-{ return * reinterpret_cast<Type*> (CharP (&X) + offset); }
+{ return * reinterpret_cast<Type*> (CharP(&X) + offset); }
 
 /* StructAfter<T>(X) returns the struct T& that is placed after X.
  * Works with X of variable size also.  X must implement get_size() */
@@ -144,7 +144,7 @@ ASSERT_STATIC (sizeof (Type) + 1 <= sizeof (_Null##Type))
 	HB_STMT_START { \
 	    if (sanitize_depth < HB_DEBUG_SANITIZE) \
 		fprintf (stderr, "SANITIZE(%p) %-*d-> %s\n", \
-			 (CharP (this) == CharP (&NullPool)) ? 0 : this, \
+			 (CharP(this) == CharP(&NullPool)) ? 0 : this, \
 			 sanitize_depth, sanitize_depth, \
 			 __PRETTY_FUNCTION__); \
 	} HB_STMT_END
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index aceb3b6..74d9b04 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -44,7 +44,7 @@
 	HB_STMT_START { \
 	    if (apply_depth < HB_DEBUG_APPLY) \
 		fprintf (stderr, "APPLY(%p) %-*d-> %s\n", \
-			 (CharP (this) == CharP (&NullPool)) ? 0 : this, \
+			 (CharP(this) == CharP(&NullPool)) ? 0 : this, \
 			 apply_depth, apply_depth, \
 			 __PRETTY_FUNCTION__); \
 	} HB_STMT_END
commit a3263aa773ad7a914496792466c69047048b093c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 18:29:09 2010 -0400

    Convert the last set of cast macros to templates

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 10de334..605d75c 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -191,8 +191,8 @@ struct OpenTypeFontFile
     if (!SANITIZE_SELF ()) return false;
     switch (tag) {
     default: return true;
-    case TrueTypeTag: case CFFTag: return SANITIZE_THIS (CAST (OffsetTable, *this, 0));
-    case TTCTag: return SANITIZE (CAST (TTCHeader, *this, 0));
+    case TrueTypeTag: case CFFTag: return SANITIZE_THIS (Cast<OffsetTable> (*this));
+    case TTCTag: return SANITIZE (Cast<TTCHeader> (*this));
     }
   }
 
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 4e8f1e4..2ef124a 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -36,30 +36,45 @@
 #define NO_INDEX		((unsigned int) 0xFFFF)
 
 
+
 /*
  * Casts
  */
 
 /* Cast to "const char *" and "char *" */
-template <typename Type> inline const char * CharP (const Type* X) { return reinterpret_cast<const char *>(X); }
-template <typename Type> inline char * CharP (Type* X) { return reinterpret_cast<char *>(X); }
+template <typename Type>
+inline const char * CharP (const Type* X)
+{ return reinterpret_cast<const char *>(X); }
+template <typename Type>
+inline char * CharP (Type* X)
+{ return reinterpret_cast<char *>(X); }
 
-#define CONST_CAST(T,X,Ofs)	(*(reinterpret_cast<const T *>(CharP(&(X)) + Ofs)))
-#define CAST(T,X,Ofs) 		(*(reinterpret_cast<T *>(CharP(&(X)) + Ofs)))
+/* Cast to struct T& */
+template<typename Type, typename TObject>
+inline const Type& Cast(const TObject &X)
+{ return reinterpret_cast<const Type&> (X); }
+template<typename Type, typename TObject>
+inline Type& Cast(TObject &X)
+{ return reinterpret_cast<Type&> (X); }
 
+/* StructAtOffset<T>(X,Ofs) returns the struct T& that is placed at memory
+ * location of X plus Ofs bytes. */
+template<typename Type, typename TObject>
+inline const Type& StructAtOffset(const TObject &X, unsigned int offset)
+{ return * reinterpret_cast<const Type*> (CharP (&X) + offset); }
+template<typename Type, typename TObject>
+inline Type& StructAtOffset(TObject &X, unsigned int offset)
+{ return * reinterpret_cast<Type*> (CharP (&X) + offset); }
 
 /* StructAfter<T>(X) returns the struct T& that is placed after X.
  * Works with X of variable size also.  X must implement get_size() */
 template<typename Type, typename TObject>
 inline const Type& StructAfter(const TObject &X)
-{
-  return * reinterpret_cast<const Type*> (CharP (&X) + X.get_size());
-}
+{ return StructAtOffset<Type>(X, X.get_size()); }
 template<typename Type, typename TObject>
 inline Type& StructAfter(TObject &X)
-{
-  return * reinterpret_cast<Type*> (CharP (&X) + X.get_size());
-}
+{ return StructAtOffset<Type>(X, X.get_size()); }
+
 
 
 /*
@@ -76,7 +91,7 @@ static const void *_NullPool[32 / sizeof (void *)];
 template <typename Type>
 static inline const Type& Null () {
   ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool));
-  return CONST_CAST (Type, *_NullPool, 0);
+  return Cast<Type> (*_NullPool);
 }
 
 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
@@ -84,7 +99,7 @@ static inline const Type& Null () {
 static const char _Null##Type[size + 1] = data; /* +1 is for nul-termination in data */ \
 template <> \
 inline const Type& Null<Type> () { \
-  return CONST_CAST (Type, *_Null##Type, 0); \
+  return Cast<Type> (*_Null##Type); \
 } /* The following line really exists such that we end in a place needing semicolon */ \
 ASSERT_STATIC (sizeof (Type) + 1 <= sizeof (_Null##Type))
 
@@ -99,14 +114,14 @@ ASSERT_STATIC (sizeof (Type) + 1 <= sizeof (_Null##Type))
   static inline const Type& get_for_data (const char *data) \
   { \
     if (HB_UNLIKELY (data == NULL)) return Null(Type); \
-    return CONST_CAST (Type, *data, 0); \
+    return Cast<Type> (*data); \
   }
 /* Like get_for_data(), but checks major version first. */
 #define STATIC_DEFINE_GET_FOR_DATA_CHECK_MAJOR_VERSION(Type, MajorMin, MajorMax) \
   static inline const Type& get_for_data (const char *data) \
   { \
     if (HB_UNLIKELY (data == NULL)) return Null(Type); \
-    const Type& t = CONST_CAST (Type, *data, 0); \
+    const Type& t = Cast<Type> (*data); \
     if (HB_UNLIKELY (t.version.major < MajorMin || t.version.major > MajorMax)) return Null(Type); \
     return t; \
   }
@@ -285,7 +300,7 @@ struct Sanitizer
     _hb_sanitize_init (&context, blob);
 
     /* We drop const here */
-    Type *t = &CAST (Type, * (char *) CharP(context.start), 0);
+    Type *t = &Cast<Type> (* (char *) CharP(context.start));
 
     sane = t->sanitize (SANITIZE_ARG_INIT);
     if (sane) {
@@ -467,7 +482,7 @@ struct GenericOffsetTo : OffsetType
   {
     unsigned int offset = *this;
     if (HB_UNLIKELY (!offset)) return Null(Type);
-    return CONST_CAST(Type, *CharP(base), offset);
+    return StructAtOffset<Type> (*CharP(base), offset);
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
@@ -475,21 +490,21 @@ struct GenericOffsetTo : OffsetType
     if (!SANITIZE_SELF ()) return false;
     unsigned int offset = *this;
     if (HB_UNLIKELY (!offset)) return true;
-    return SANITIZE (CAST(Type, *CharP(base), offset)) || NEUTER (*this, 0);
+    return SANITIZE (StructAtOffset<Type> (*CharP(base), offset)) || NEUTER (*this, 0);
   }
   inline bool sanitize (SANITIZE_ARG_DEF, void *base, void *base2) {
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
     unsigned int offset = *this;
     if (HB_UNLIKELY (!offset)) return true;
-    return SANITIZE_BASE (CAST(Type, *CharP(base), offset), base2) || NEUTER (*this, 0);
+    return SANITIZE_BASE (StructAtOffset<Type> (*CharP(base), offset), base2) || NEUTER (*this, 0);
   }
   inline bool sanitize (SANITIZE_ARG_DEF, void *base, unsigned int user_data) {
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
     unsigned int offset = *this;
     if (HB_UNLIKELY (!offset)) return true;
-    return SANITIZE_BASE (CAST(Type, *CharP(base), offset), user_data) || NEUTER (*this, 0);
+    return SANITIZE_BASE (StructAtOffset<Type> (*CharP(base), offset), user_data) || NEUTER (*this, 0);
   }
 };
 template <typename Base, typename OffsetType, typename Type>
diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 75dcd4c..c8b2b33 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -591,7 +591,7 @@ struct PairPosFormat1
 	buffer->in_pos = j;
 	return true;
       }
-      record = &CONST_CAST (PairValueRecord, *record, record_size);
+      record = &StructAtOffset<PairValueRecord> (*record, record_size);
     }
 
     return false;
@@ -1361,7 +1361,7 @@ struct ExtensionPos : Extension
   {
     unsigned int offset = get_offset ();
     if (HB_UNLIKELY (!offset)) return Null(PosLookupSubTable);
-    return CONST_CAST (PosLookupSubTable, *this, offset);
+    return StructAtOffset<PosLookupSubTable> (*this, offset);
   }
 
   inline bool apply (APPLY_ARG_DEF) const;
@@ -1445,7 +1445,7 @@ struct PosLookupSubTable
 struct PosLookup : Lookup
 {
   inline const PosLookupSubTable& get_subtable (unsigned int i) const
-  { return this+CONST_CAST (OffsetArrayOf<PosLookupSubTable>, subTable, 0)[i]; }
+  { return this+Cast<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
 
   /* Like get_type(), but looks through extension lookups.
    * Never returns Extension */
@@ -1524,7 +1524,7 @@ struct PosLookup : Lookup
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (HB_UNLIKELY (!Lookup::sanitize (SANITIZE_ARG))) return false;
-    OffsetArrayOf<PosLookupSubTable> &list = CAST (OffsetArrayOf<PosLookupSubTable>, subTable, 0);
+    OffsetArrayOf<PosLookupSubTable> &list = Cast<OffsetArrayOf<PosLookupSubTable> > (subTable);
     return SANITIZE_THIS (list);
   }
 };
@@ -1541,10 +1541,10 @@ struct GPOS : GSUBGPOS
   static const hb_tag_t Tag	= HB_OT_TAG_GPOS;
 
   static inline const GPOS& get_for_data (const char *data)
-  { return CONST_CAST(GPOS, GSUBGPOS::get_for_data (data), 0); }
+  { return Cast<GPOS> (GSUBGPOS::get_for_data (data)); }
 
   inline const PosLookup& get_lookup (unsigned int i) const
-  { return CONST_CAST(PosLookup, GSUBGPOS::get_lookup (i), 0); }
+  { return Cast<PosLookup> (GSUBGPOS::get_lookup (i)); }
 
   inline bool position_lookup (hb_ot_layout_context_t *context,
 			       hb_buffer_t  *buffer,
@@ -1555,7 +1555,7 @@ struct GPOS : GSUBGPOS
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (HB_UNLIKELY (!GSUBGPOS::sanitize (SANITIZE_ARG))) return false;
-    OffsetTo<PosLookupList> &list = CAST(OffsetTo<PosLookupList>, lookupList, 0);
+    OffsetTo<PosLookupList> &list = Cast<OffsetTo<PosLookupList> > (lookupList);
     return SANITIZE_THIS (list);
   }
 };
@@ -1583,7 +1583,7 @@ inline bool ExtensionPos::sanitize (SANITIZE_ARG_DEF)
 
   unsigned int offset = get_offset ();
   if (HB_UNLIKELY (!offset)) return true;
-  return SANITIZE (CAST (PosLookupSubTable, *this, offset));
+  return SANITIZE (StructAtOffset<PosLookupSubTable> (*this, offset));
 }
 
 static inline bool position_lookup (APPLY_ARG_DEF, unsigned int lookup_index)
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 23150b6..fd44575 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -566,7 +566,7 @@ struct ExtensionSubst : Extension
   {
     unsigned int offset = get_offset ();
     if (HB_UNLIKELY (!offset)) return Null(SubstLookupSubTable);
-    return CONST_CAST (SubstLookupSubTable, *this, offset);
+    return StructAtOffset<SubstLookupSubTable> (*this, offset);
   }
 
   inline bool apply (APPLY_ARG_DEF) const;
@@ -740,7 +740,7 @@ struct SubstLookupSubTable
 struct SubstLookup : Lookup
 {
   inline const SubstLookupSubTable& get_subtable (unsigned int i) const
-  { return this+CONST_CAST (OffsetArrayOf<SubstLookupSubTable>, subTable, 0)[i]; }
+  { return this+Cast<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; }
 
   /* Like get_type(), but looks through extension lookups.
    * Never returns Extension */
@@ -833,7 +833,7 @@ struct SubstLookup : Lookup
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (HB_UNLIKELY (!Lookup::sanitize (SANITIZE_ARG))) return false;
-    OffsetArrayOf<SubstLookupSubTable> &list = CAST (OffsetArrayOf<SubstLookupSubTable>, subTable, 0);
+    OffsetArrayOf<SubstLookupSubTable> &list = Cast<OffsetArrayOf<SubstLookupSubTable> > (subTable);
     return SANITIZE_THIS (list);
   }
 };
@@ -850,10 +850,10 @@ struct GSUB : GSUBGPOS
   static const hb_tag_t Tag	= HB_OT_TAG_GSUB;
 
   static inline const GSUB& get_for_data (const char *data)
-  { return CONST_CAST(GSUB, GSUBGPOS::get_for_data (data), 0); }
+  { return Cast<GSUB> (GSUBGPOS::get_for_data (data)); }
 
   inline const SubstLookup& get_lookup (unsigned int i) const
-  { return CONST_CAST(SubstLookup, GSUBGPOS::get_lookup (i), 0); }
+  { return Cast<SubstLookup> (GSUBGPOS::get_lookup (i)); }
 
   inline bool substitute_lookup (hb_ot_layout_context_t *context,
 				 hb_buffer_t  *buffer,
@@ -865,7 +865,7 @@ struct GSUB : GSUBGPOS
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (HB_UNLIKELY (!GSUBGPOS::sanitize (SANITIZE_ARG))) return false;
-    OffsetTo<SubstLookupList> &list = CAST(OffsetTo<SubstLookupList>, lookupList, 0);
+    OffsetTo<SubstLookupList> &list = Cast<OffsetTo<SubstLookupList> > (lookupList);
     return SANITIZE_THIS (list);
   }
 };
@@ -893,7 +893,7 @@ inline bool ExtensionSubst::sanitize (SANITIZE_ARG_DEF)
 
   unsigned int offset = get_offset ();
   if (HB_UNLIKELY (!offset)) return true;
-  return SANITIZE (CAST (SubstLookupSubTable, *this, offset));
+  return SANITIZE (StructAtOffset<SubstLookupSubTable> (*this, offset));
 }
 
 static inline bool substitute_lookup (APPLY_ARG_DEF, unsigned int lookup_index)
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 3e4adff..aceb3b6 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -299,10 +299,10 @@ struct Rule
   inline bool apply (APPLY_ARG_DEF, ContextLookupContext &lookup_context) const
   {
     TRACE_APPLY ();
-    const LookupRecord *lookupRecord = &CONST_CAST (LookupRecord, input, input[0].get_size () * (inputCount ? inputCount - 1 : 0));
+    const LookupRecord &lookupRecord = StructAtOffset<LookupRecord> (input, input[0].get_size () * (inputCount ? inputCount - 1 : 0));
     return context_lookup (APPLY_ARG,
 			   inputCount, input,
-			   lookupCount, lookupRecord,
+			   lookupCount, &lookupRecord,
 			   lookup_context);
   }
 
@@ -448,14 +448,14 @@ struct ContextFormat3
     if (HB_LIKELY (index == NOT_COVERED))
       return false;
 
-    const LookupRecord *lookupRecord = &CONST_CAST(LookupRecord, coverage, coverage[0].get_size () * glyphCount);
+    const LookupRecord &lookupRecord = StructAtOffset<LookupRecord> (coverage, coverage[0].get_size () * glyphCount);
     struct ContextLookupContext lookup_context = {
       {match_coverage, apply_func},
        CharP(this)
     };
     return context_lookup (APPLY_ARG,
 			   glyphCount, (const USHORT *) (coverage + 1),
-			   lookupCount, lookupRecord,
+			   lookupCount, &lookupRecord,
 			   lookup_context);
   }
 
@@ -466,8 +466,8 @@ struct ContextFormat3
     if (!SANITIZE_ARRAY (coverage, OffsetTo<Coverage>::get_size (), glyphCount)) return false;
     for (unsigned int i = 0; i < count; i++)
       if (!SANITIZE_THIS (coverage[i])) return false;
-    LookupRecord *lookupRecord = &CAST(LookupRecord, coverage, OffsetTo<Coverage>::get_size () * glyphCount);
-    return SANITIZE_ARRAY (lookupRecord, LookupRecord::get_size (), lookupCount);
+    LookupRecord &lookupRecord = StructAtOffset<LookupRecord> (coverage, OffsetTo<Coverage>::get_size () * glyphCount);
+    return SANITIZE_ARRAY (&lookupRecord, LookupRecord::get_size (), lookupCount);
   }
 
   private:
commit c38188a1912f72d9ef90ae1bcbdbba7ecce63371
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 16:52:09 2010 -0400

    Remove unused macro

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index fde4d7f..4e8f1e4 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -45,7 +45,6 @@ template <typename Type> inline const char * CharP (const Type* X) { return rein
 template <typename Type> inline char * CharP (Type* X) { return reinterpret_cast<char *>(X); }
 
 #define CONST_CAST(T,X,Ofs)	(*(reinterpret_cast<const T *>(CharP(&(X)) + Ofs)))
-#define DECONST_CAST(T,X,Ofs)	(*(reinterpret_cast<T *>((char *)CharP(&(X)) + Ofs)))
 #define CAST(T,X,Ofs) 		(*(reinterpret_cast<T *>(CharP(&(X)) + Ofs)))
 
 
commit 3b2c2df41b90f2a1d9e33b3dc15a92cff58a689a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 16:51:42 2010 -0400

    Cleanup Extension sanitize()

diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 9c3de50..cfbca1d 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -264,21 +264,8 @@ struct LookupFlag : USHORT
 };
 ASSERT_SIZE (LookupFlag, 2);
 
-struct LookupSubTable
-{
-  inline bool sanitize (SANITIZE_ARG_DEF) {
-    TRACE_SANITIZE ();
-    return SANITIZE_SELF ();
-  }
-
-  private:
-  USHORT	format;		/* Subtable format.  Different for GSUB and GPOS */
-};
-ASSERT_SIZE (LookupSubTable, 2);
-
 struct Lookup
 {
-  inline const LookupSubTable& get_subtable (unsigned int i) const { return this+subTable[i]; }
   inline unsigned int get_subtable_count (void) const { return subTable.len; }
 
   inline unsigned int get_type (void) const { return lookupType; }
@@ -295,9 +282,8 @@ struct Lookup
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    /* We sanitize subtables shallow here since we don't have their actual
-     * type.  Real sanitize of the referenced data is done by GSUB/GPOS/... */
-    if (!(SANITIZE_SELF () && HB_LIKELY (subTable.sanitize_shallow (SANITIZE_ARG)))) return false;
+    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
+    if (!(SANITIZE_SELF () && HB_LIKELY (subTable.sanitize (SANITIZE_ARG)))) return false;
     if (HB_UNLIKELY (lookupFlag & LookupFlag::UseMarkFilteringSet))
     {
       USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
@@ -308,7 +294,7 @@ struct Lookup
 
   USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
   USHORT	lookupFlag;		/* Lookup qualifiers */
-  OffsetArrayOf<LookupSubTable>
+  ArrayOf<Offset>
 		subTable;		/* Array of SubTables */
   USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
 					 * structure. This field is only present if bit
diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index f5348f4..75dcd4c 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -1358,7 +1358,11 @@ struct ExtensionPos : Extension
 
   private:
   inline const struct PosLookupSubTable& get_subtable (void) const
-  { return CONST_CAST (PosLookupSubTable, Extension::get_subtable (), 0); }
+  {
+    unsigned int offset = get_offset ();
+    if (HB_UNLIKELY (!offset)) return Null(PosLookupSubTable);
+    return CONST_CAST (PosLookupSubTable, *this, offset);
+  }
 
   inline bool apply (APPLY_ARG_DEF) const;
 
@@ -1519,7 +1523,7 @@ struct PosLookup : Lookup
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    if (!Lookup::sanitize (SANITIZE_ARG)) return false;
+    if (HB_UNLIKELY (!Lookup::sanitize (SANITIZE_ARG))) return false;
     OffsetArrayOf<PosLookupSubTable> &list = CAST (OffsetArrayOf<PosLookupSubTable>, subTable, 0);
     return SANITIZE_THIS (list);
   }
@@ -1550,7 +1554,7 @@ struct GPOS : GSUBGPOS
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    if (!GSUBGPOS::sanitize (SANITIZE_ARG)) return false;
+    if (HB_UNLIKELY (!GSUBGPOS::sanitize (SANITIZE_ARG))) return false;
     OffsetTo<PosLookupList> &list = CAST(OffsetTo<PosLookupList>, lookupList, 0);
     return SANITIZE_THIS (list);
   }
@@ -1574,10 +1578,12 @@ inline bool ExtensionPos::apply (APPLY_ARG_DEF) const
 inline bool ExtensionPos::sanitize (SANITIZE_ARG_DEF)
 {
   TRACE_SANITIZE ();
-  return Extension::sanitize (SANITIZE_ARG) &&
-	 (&(Extension::get_subtable ()) == &Null(LookupSubTable) ||
-	  get_type () == PosLookupSubTable::Extension ||
-	  DECONST_CAST (PosLookupSubTable, get_subtable (), 0).sanitize (SANITIZE_ARG));
+  if (HB_UNLIKELY (!Extension::sanitize (SANITIZE_ARG))) return false;
+  if (HB_UNLIKELY (get_type () == PosLookupSubTable::Extension)) return false;
+
+  unsigned int offset = get_offset ();
+  if (HB_UNLIKELY (!offset)) return true;
+  return SANITIZE (CAST (PosLookupSubTable, *this, offset));
 }
 
 static inline bool position_lookup (APPLY_ARG_DEF, unsigned int lookup_index)
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 65402b8..23150b6 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -563,7 +563,11 @@ struct ExtensionSubst : Extension
 
   private:
   inline const struct SubstLookupSubTable& get_subtable (void) const
-  { return CONST_CAST (SubstLookupSubTable, Extension::get_subtable (), 0); }
+  {
+    unsigned int offset = get_offset ();
+    if (HB_UNLIKELY (!offset)) return Null(SubstLookupSubTable);
+    return CONST_CAST (SubstLookupSubTable, *this, offset);
+  }
 
   inline bool apply (APPLY_ARG_DEF) const;
 
@@ -828,7 +832,7 @@ struct SubstLookup : Lookup
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    if (!Lookup::sanitize (SANITIZE_ARG)) return false;
+    if (HB_UNLIKELY (!Lookup::sanitize (SANITIZE_ARG))) return false;
     OffsetArrayOf<SubstLookupSubTable> &list = CAST (OffsetArrayOf<SubstLookupSubTable>, subTable, 0);
     return SANITIZE_THIS (list);
   }
@@ -860,7 +864,7 @@ struct GSUB : GSUBGPOS
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    if (!GSUBGPOS::sanitize (SANITIZE_ARG)) return false;
+    if (HB_UNLIKELY (!GSUBGPOS::sanitize (SANITIZE_ARG))) return false;
     OffsetTo<SubstLookupList> &list = CAST(OffsetTo<SubstLookupList>, lookupList, 0);
     return SANITIZE_THIS (list);
   }
@@ -884,10 +888,12 @@ inline bool ExtensionSubst::apply (APPLY_ARG_DEF) const
 inline bool ExtensionSubst::sanitize (SANITIZE_ARG_DEF)
 {
   TRACE_SANITIZE ();
-  return Extension::sanitize (SANITIZE_ARG) &&
-	 (&(Extension::get_subtable ()) == &Null(LookupSubTable) ||
-	  get_type () == SubstLookupSubTable::Extension ||
-	  DECONST_CAST (SubstLookupSubTable, get_subtable (), 0).sanitize (SANITIZE_ARG));
+  if (HB_UNLIKELY (!Extension::sanitize (SANITIZE_ARG))) return false;
+  if (HB_UNLIKELY (get_type () == SubstLookupSubTable::Extension)) return false;
+
+  unsigned int offset = get_offset ();
+  if (HB_UNLIKELY (!offset)) return true;
+  return SANITIZE (CAST (SubstLookupSubTable, *this, offset));
 }
 
 static inline bool substitute_lookup (APPLY_ARG_DEF, unsigned int lookup_index)
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 2856d34..3e4adff 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -836,12 +836,7 @@ struct ExtensionFormat1
 
   protected:
   inline unsigned int get_type (void) const { return extensionLookupType; }
-  inline const LookupSubTable& get_subtable (void) const
-  {
-    unsigned int offset = extensionOffset;
-    if (HB_UNLIKELY (!offset)) return Null(LookupSubTable);
-    return CONST_CAST (LookupSubTable, *this, offset);
-  }
+  inline unsigned int get_offset (void) const { return extensionOffset; }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
@@ -867,11 +862,11 @@ struct Extension
     default:return 0;
     }
   }
-  inline const LookupSubTable& get_subtable (void) const
+  inline unsigned int get_offset (void) const
   {
     switch (u.format) {
-    case 1: return u.format1->get_subtable ();
-    default:return Null(LookupSubTable);
+    case 1: return u.format1->get_offset ();
+    default:return 0;
     }
   }
 
commit 1856184b93760a1a54fb1a3c54281bb252df7ce6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 14:15:11 2010 -0400

    Fail sanitize on major version mismatch
    
    We handle major-version differences via get_for_data(), so sanitize
    should never see a major version mismatch.

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 91854f8..10de334 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -139,8 +139,8 @@ struct TTCHeader
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (!SANITIZE (version)) return false;
-    if (version.major < 1 || version.major > 2) return true;
-    return table.sanitize (SANITIZE_ARG, CharP(this), CharP(this));
+    if (HB_UNLIKELY (version.major < 1 || version.major > 2)) return false;
+    return HB_LIKELY (table.sanitize (SANITIZE_ARG, CharP(this), CharP(this)));
   }
 
   private:
diff --git a/src/hb-ot-layout-gdef-private.hh b/src/hb-ot-layout-gdef-private.hh
index 4f6c1d9..4de5740 100644
--- a/src/hb-ot-layout-gdef-private.hh
+++ b/src/hb-ot-layout-gdef-private.hh
@@ -346,7 +346,7 @@ struct GDEF
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (!SANITIZE (version)) return false;
-    if (version.major != 1) return true;
+    if (HB_UNLIKELY (version.major != 1)) return false;
     return SANITIZE_THIS2 (glyphClassDef, attachList) &&
 	   SANITIZE_THIS2 (ligCaretList, markAttachClassDef) &&
 	   (version < 0x00010002 || SANITIZE_THIS (markGlyphSetsDef[0]));
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index c5639bb..2856d34 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -937,7 +937,7 @@ struct GSUBGPOS
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (!SANITIZE (version)) return false;
-    if (version.major != 1) return true;
+    if (HB_UNLIKELY (version.major != 1)) return false;
     return SANITIZE_THIS3 (scriptList, featureList, lookupList);
   }
 
commit df3f505dcfeefc8cd395900b116767d22549f756
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 14:11:33 2010 -0400

    More sanitize cleanup

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 993e7eb..91854f8 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -110,16 +110,7 @@ typedef struct OffsetTable
   public:
   inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
     TRACE_SANITIZE ();
-    if (!(SANITIZE_SELF () && SANITIZE_ARRAY (tableDir, TableDirectory::get_size (), numTables))) return false;
-    return true;
-    /* No need to check tables individually since we don't sanitize the
-     * referenced table, just the table directory.  Code retaind to make
-     * sure TableDirectory has a baseless sanitize(). */
-    unsigned int count = numTables;
-    for (unsigned int i = 0; i < count; i++)
-      if (!SANITIZE (tableDir[i]))
-        return false;
-    return true;
+    return SANITIZE_SELF () && SANITIZE_ARRAY (tableDir, TableDirectory::get_size (), numTables);
   }
 
   private:
@@ -143,11 +134,7 @@ struct TTCHeader
   STATIC_DEFINE_GET_FOR_DATA_CHECK_MAJOR_VERSION (TTCHeader, 1, 2);
 
   inline unsigned int get_face_count (void) const { return table.len; }
-
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    return this+table[i];
-  }
+  inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
@@ -199,13 +186,6 @@ struct OpenTypeFontFile
     }
   }
 
-  /* This is how you get a table */
-  inline const char* get_table_data (const OpenTypeTable& table) const
-  {
-    if (HB_UNLIKELY (table.offset == 0)) return NULL;
-    return CharP(this) + table.offset;
-  }
-
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
diff --git a/src/main.cc b/src/main.cc
index 0251759..b2aee2b 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -99,7 +99,7 @@ main (int argc, char **argv)
       case GSUBGPOS::GPOSTag:
 	{
 
-	const GSUBGPOS &g = GSUBGPOS::get_for_data (ot.get_table_data (table));
+	const GSUBGPOS &g = GSUBGPOS::get_for_data ((const char *) &ot + table.offset);
 
 	int num_scripts = g.get_script_count ();
 	printf ("    %d script(s) found in table\n", num_scripts);
@@ -162,7 +162,7 @@ main (int argc, char **argv)
       case GDEF::Tag:
 	{
 
-	const GDEF &gdef = GDEF::get_for_data (ot.get_table_data (table));
+	const GDEF &gdef = GDEF::get_for_data ((const char *) &ot + table.offset);
 
 	printf ("    Has %sglyph classes\n",
 		  gdef.has_glyph_classes () ? "" : "no ");
commit 278a91f0cd802ac817c2603429bae1fa4a350ea0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 13:59:39 2010 -0400

    Minor cleanup of sanitize
    
    Done with an audit of all sanitize()

diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 895bdca..f5348f4 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -171,6 +171,7 @@ struct ValueFormat : USHORT
     return true;
   }
 
+  /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
   inline bool sanitize_values_stride_unsafe (SANITIZE_ARG_DEF, void *base, const Value *values, unsigned int count, unsigned int stride) {
     TRACE_SANITIZE ();
 
@@ -537,7 +538,7 @@ struct PairSet
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
     unsigned int count = (1 + format_len) * len;
-    return SANITIZE_MEM (array, USHORT::get_size () * count);
+    return SANITIZE_ARRAY (array, USHORT::get_size (), count);
   }
 
   private:
@@ -603,7 +604,7 @@ struct PairPosFormat1
     unsigned int len2 = valueFormat2.get_len ();
 
     if (!(SANITIZE_SELF () && SANITIZE_THIS (coverage) &&
-	  pairSet.sanitize (SANITIZE_ARG, CharP(this), len1 + len2))) return false;
+	  HB_LIKELY (pairSet.sanitize (SANITIZE_ARG, CharP(this), len1 + len2)))) return false;
 
     if (!(valueFormat1.has_device () || valueFormat2.has_device ())) return true;
 
@@ -1050,8 +1051,8 @@ struct MarkBasePosFormat1
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    return SANITIZE_SELF () && SANITIZE_THIS2 (markCoverage, baseCoverage) &&
-	   SANITIZE_THIS (markArray) && baseArray.sanitize (SANITIZE_ARG, CharP(this), classCount);
+    return SANITIZE_SELF () && SANITIZE_THIS3 (markCoverage, baseCoverage, markArray) &&
+	   HB_LIKELY (baseArray.sanitize (SANITIZE_ARG, CharP(this), classCount));
   }
 
   private:
@@ -1170,9 +1171,8 @@ struct MarkLigPosFormat1
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    return SANITIZE_SELF () &&
-	   SANITIZE_THIS2 (markCoverage, ligatureCoverage) &&
-	   SANITIZE_THIS (markArray) && ligatureArray.sanitize (SANITIZE_ARG, CharP(this), classCount);
+    return SANITIZE_SELF () && SANITIZE_THIS3 (markCoverage, ligatureCoverage, markArray) &&
+	   HB_LIKELY (ligatureArray.sanitize (SANITIZE_ARG, CharP(this), classCount));
   }
 
   private:
@@ -1270,8 +1270,8 @@ struct MarkMarkPosFormat1
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    return SANITIZE_SELF () && SANITIZE_THIS2 (mark1Coverage, mark2Coverage) &&
-	   SANITIZE_THIS (mark1Array) && mark2Array.sanitize (SANITIZE_ARG, CharP(this), classCount);
+    return SANITIZE_SELF () && SANITIZE_THIS3 (mark1Coverage, mark2Coverage, mark1Array) &&
+	   HB_LIKELY (mark2Array.sanitize (SANITIZE_ARG, CharP(this), classCount));
   }
 
   private:
commit 9ac7dc73bc24b6dafb94df5de9cbf8fa0c82d5bc
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 13:50:22 2010 -0400

    Check for (impossible) overflow

diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 494f599..895bdca 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -322,6 +322,7 @@ struct AnchorMatrix
   inline bool sanitize (SANITIZE_ARG_DEF, unsigned int cols) {
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
+    if (HB_UNLIKELY (cols >= ((unsigned int) -1) / rows)) return false;
     unsigned int count = rows * cols;
     if (!SANITIZE_ARRAY (matrix, matrix[0].get_size (), count)) return false;
     for (unsigned int i = 0; i < count; i++)
commit 9fc8684fd85ef6ec82b3b54323761bbdd4c3d891
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 13:37:58 2010 -0400

    Cleanup ContextFormat3 sanitize

diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index a68e5a4..c5639bb 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -463,10 +463,11 @@ struct ContextFormat3
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
     unsigned int count = glyphCount;
+    if (!SANITIZE_ARRAY (coverage, OffsetTo<Coverage>::get_size (), glyphCount)) return false;
     for (unsigned int i = 0; i < count; i++)
       if (!SANITIZE_THIS (coverage[i])) return false;
-    LookupRecord *lookupRecord = &CAST(LookupRecord, coverage, coverage[0].get_size () * glyphCount);
-    return SANITIZE_MEM (lookupRecord, lookupRecord[0].get_size () * lookupCount);
+    LookupRecord *lookupRecord = &CAST(LookupRecord, coverage, OffsetTo<Coverage>::get_size () * glyphCount);
+    return SANITIZE_ARRAY (lookupRecord, LookupRecord::get_size (), lookupCount);
   }
 
   private:
commit e77302c61f1f1620d1f438a997575fa6ee5c172e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 13:34:00 2010 -0400

    Add comment

diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 81e4dc9..9c3de50 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -295,7 +295,9 @@ struct Lookup
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    if (!(SANITIZE_SELF () && HB_LIKELY ((subTable).sanitize_shallow (SANITIZE_ARG)))) return false;
+    /* We sanitize subtables shallow here since we don't have their actual
+     * type.  Real sanitize of the referenced data is done by GSUB/GPOS/... */
+    if (!(SANITIZE_SELF () && HB_LIKELY (subTable.sanitize_shallow (SANITIZE_ARG)))) return false;
     if (HB_UNLIKELY (lookupFlag & LookupFlag::UseMarkFilteringSet))
     {
       USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
commit 7c469c3ca4ed4e45c50eff70df59b1a4780bae5b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 13:26:21 2010 -0400

    Minor

diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 4973a13..81e4dc9 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -202,7 +202,7 @@ struct Script
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    return SANITIZE_THIS (defaultLangSys) && SANITIZE_THIS (langSys);
+    return SANITIZE_THIS2 (defaultLangSys, langSys);
   }
 
   private:
commit dc228048a813e43356373505168d3822deea5d72
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 13:22:41 2010 -0400

    Remove integrity check in Tag sanitize
    
    Serves no useful purpose.

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index d1bcf8e..fde4d7f 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -406,15 +406,6 @@ struct Tag : ULONG
   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
   inline operator const char* (void) const { return CharP(this); }
   inline operator char* (void) { return CharP(this); }
-
-  inline bool sanitize (SANITIZE_ARG_DEF) {
-    TRACE_SANITIZE ();
-    /* Note: Only accept ASCII-visible tags (mind DEL)
-     * This is one of the few places (only place?) that we check
-     * for data integrity, as opposed to just boundary checks.
-     */
-    return SANITIZE_SELF () && (((uint32_t) *this) & 0x80808080) == 0;
-  }
 };
 ASSERT_SIZE (Tag, 4);
 DEFINE_NULL_DATA (Tag, 4, "    ");
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 38d1983..4973a13 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -55,7 +55,7 @@ struct Record
 
   inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
     TRACE_SANITIZE ();
-    return SANITIZE (tag) && SANITIZE_BASE (offset, base);
+    return SANITIZE_SELF () && SANITIZE_BASE (offset, base);
   }
 
   Tag		tag;		/* 4-byte Tag identifier */
commit 8015a8c762dc7be36998d529b7a3af59e3d14d87
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 11:06:30 2010 -0400

    Don't sanitize raw table data
    
    That part is performed by individual table sanitize.

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index bd8a022..993e7eb 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -49,10 +49,9 @@ typedef struct TableDirectory
 {
   static inline unsigned int get_size () { return sizeof (TableDirectory); }
 
-  inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
+  inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    return SANITIZE_SELF () && SANITIZE (tag) &&
-	   SANITIZE_MEM (CharP(base) + (unsigned long) offset, length);
+    return SANITIZE_SELF ();
   }
 
   Tag		tag;		/* 4-byte identifier. */
@@ -109,12 +108,16 @@ typedef struct OffsetTable
   inline unsigned int get_face_count (void) const { return 1; }
 
   public:
-  inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
+  inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
     TRACE_SANITIZE ();
     if (!(SANITIZE_SELF () && SANITIZE_ARRAY (tableDir, TableDirectory::get_size (), numTables))) return false;
+    return true;
+    /* No need to check tables individually since we don't sanitize the
+     * referenced table, just the table directory.  Code retaind to make
+     * sure TableDirectory has a baseless sanitize(). */
     unsigned int count = numTables;
     for (unsigned int i = 0; i < count; i++)
-      if (!SANITIZE_BASE (tableDir[i], base))
+      if (!SANITIZE (tableDir[i]))
         return false;
     return true;
   }
@@ -200,7 +203,7 @@ struct OpenTypeFontFile
   inline const char* get_table_data (const OpenTypeTable& table) const
   {
     if (HB_UNLIKELY (table.offset == 0)) return NULL;
-    return ((const char*) this) + table.offset;
+    return CharP(this) + table.offset;
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
commit c293581e962b7982622e7d607fa3909b40da718e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 11:15:46 2010 -0400

    Add coment

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 78208a2..d1bcf8e 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -285,6 +285,7 @@ struct Sanitizer
 
     _hb_sanitize_init (&context, blob);
 
+    /* We drop const here */
     Type *t = &CAST (Type, * (char *) CharP(context.start), 0);
 
     sane = t->sanitize (SANITIZE_ARG_INIT);
commit 1faa76c6e848c6b0e360d9ddcf567533b87f8f31
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 10:54:26 2010 -0400

    Remove unnecessary casts

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index de5b165..78208a2 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -264,7 +264,7 @@ _hb_sanitize_edit (SANITIZE_ARG_DEF,
 
 #define NEUTER(Var, Val) \
 	(SANITIZE_OBJ (Var) && \
-	 _hb_sanitize_edit (SANITIZE_ARG, CharP(&(Var)), sizeof (Var)) && \
+	 _hb_sanitize_edit (SANITIZE_ARG, CharP(&(Var)), (Var).get_size ()) && \
 	 ((Var).set (Val), true))
 
 
@@ -484,21 +484,21 @@ struct GenericOffsetTo : OffsetType
     if (!SANITIZE_SELF ()) return false;
     unsigned int offset = *this;
     if (HB_UNLIKELY (!offset)) return true;
-    return SANITIZE (CAST(Type, *CharP(base), offset)) || NEUTER (CAST(OffsetType,*this,0), 0);
+    return SANITIZE (CAST(Type, *CharP(base), offset)) || NEUTER (*this, 0);
   }
   inline bool sanitize (SANITIZE_ARG_DEF, void *base, void *base2) {
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
     unsigned int offset = *this;
     if (HB_UNLIKELY (!offset)) return true;
-    return SANITIZE_BASE (CAST(Type, *CharP(base), offset), base2) || NEUTER (CAST(OffsetType,*this,0), 0);
+    return SANITIZE_BASE (CAST(Type, *CharP(base), offset), base2) || NEUTER (*this, 0);
   }
   inline bool sanitize (SANITIZE_ARG_DEF, void *base, unsigned int user_data) {
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
     unsigned int offset = *this;
     if (HB_UNLIKELY (!offset)) return true;
-    return SANITIZE_BASE (CAST(Type, *CharP(base), offset), user_data) || NEUTER (CAST(OffsetType,*this,0), 0);
+    return SANITIZE_BASE (CAST(Type, *CharP(base), offset), user_data) || NEUTER (*this, 0);
   }
 };
 template <typename Base, typename OffsetType, typename Type>
commit 079dc40112d3908ff7b7028ea3019bfe82bf606d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 10:47:12 2010 -0400

    Avoid overflow in TableDirectory sanitize

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 091d994..bd8a022 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -111,7 +111,7 @@ typedef struct OffsetTable
   public:
   inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
     TRACE_SANITIZE ();
-    if (!(SANITIZE_SELF () && SANITIZE_MEM (tableDir, tableDir[0].get_size () * numTables))) return false;
+    if (!(SANITIZE_SELF () && SANITIZE_ARRAY (tableDir, TableDirectory::get_size (), numTables))) return false;
     unsigned int count = numTables;
     for (unsigned int i = 0; i < count; i++)
       if (!SANITIZE_BASE (tableDir[i], base))
commit fb5904ec935d925a423401bc975ffaa22022ce1b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Apr 22 10:43:30 2010 -0400

    Make casts more explicit

diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 1454b5b..494f599 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -1536,10 +1536,10 @@ struct GPOS : GSUBGPOS
   static const hb_tag_t Tag	= HB_OT_TAG_GPOS;
 
   static inline const GPOS& get_for_data (const char *data)
-  { return (const GPOS&) GSUBGPOS::get_for_data (data); }
+  { return CONST_CAST(GPOS, GSUBGPOS::get_for_data (data), 0); }
 
   inline const PosLookup& get_lookup (unsigned int i) const
-  { return (const PosLookup&) GSUBGPOS::get_lookup (i); }
+  { return CONST_CAST(PosLookup, GSUBGPOS::get_lookup (i), 0); }
 
   inline bool position_lookup (hb_ot_layout_context_t *context,
 			       hb_buffer_t  *buffer,
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index d04ea99..65402b8 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -846,10 +846,10 @@ struct GSUB : GSUBGPOS
   static const hb_tag_t Tag	= HB_OT_TAG_GSUB;
 
   static inline const GSUB& get_for_data (const char *data)
-  { return (const GSUB&) GSUBGPOS::get_for_data (data); }
+  { return CONST_CAST(GSUB, GSUBGPOS::get_for_data (data), 0); }
 
   inline const SubstLookup& get_lookup (unsigned int i) const
-  { return (const SubstLookup&) GSUBGPOS::get_lookup (i); }
+  { return CONST_CAST(SubstLookup, GSUBGPOS::get_lookup (i), 0); }
 
   inline bool substitute_lookup (hb_ot_layout_context_t *context,
 				 hb_buffer_t  *buffer,



More information about the HarfBuzz mailing list