summaryrefslogtreecommitdiff
path: root/pango/opentype/hb-open-types-private.hh
diff options
context:
space:
mode:
Diffstat (limited to 'pango/opentype/hb-open-types-private.hh')
-rw-r--r--pango/opentype/hb-open-types-private.hh105
1 files changed, 102 insertions, 3 deletions
diff --git a/pango/opentype/hb-open-types-private.hh b/pango/opentype/hb-open-types-private.hh
index 98efde47..a8549e2b 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()