summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh178
1 files changed, 115 insertions, 63 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
index 046df97659..75a0f568d1 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh
@@ -179,10 +179,13 @@ struct hb_sanitize_context_t
inline const char *get_name (void) { return "SANITIZE"; }
static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE;
typedef bool return_t;
+ template <typename T, typename F>
+ inline bool may_dispatch (const T *obj, const F *format)
+ { return format->sanitize (this); }
template <typename T>
inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
static return_t default_return_value (void) { return true; }
- bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; }
+ bool stop_sublookup_iteration (const return_t r) const { return !r; }
inline void init (hb_blob_t *b)
{
@@ -194,10 +197,11 @@ struct hb_sanitize_context_t
{
this->start = hb_blob_get_data (this->blob, NULL);
this->end = this->start + hb_blob_get_length (this->blob);
+ assert (this->start <= this->end); /* Must not overflow. */
this->edit_count = 0;
this->debug_depth = 0;
- DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, +1,
+ DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
"start [%p..%p] (%lu bytes)",
this->start, this->end,
(unsigned long) (this->end - this->start));
@@ -205,7 +209,7 @@ struct hb_sanitize_context_t
inline void end_processing (void)
{
- DEBUG_MSG_LEVEL (SANITIZE, this->blob, 0, -1,
+ DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
"end [%p..%p] %u edit requests",
this->start, this->end, this->edit_count);
@@ -217,28 +221,31 @@ struct hb_sanitize_context_t
inline bool check_range (const void *base, unsigned int len) const
{
const char *p = (const char *) base;
+ bool ok = this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len;
- hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
- (&this->debug_depth, "SANITIZE", this->blob, NULL,
- "check_range [%p..%p] (%d bytes) in [%p..%p]",
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
p, p + len, len,
- this->start, this->end);
+ this->start, this->end,
+ ok ? "OK" : "OUT-OF-RANGE");
- return TRACE_RETURN (likely (this->start <= p && p <= this->end && (unsigned int) (this->end - p) >= len));
+ return likely (ok);
}
inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
{
const char *p = (const char *) base;
bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
+ unsigned int array_size = record_size * len;
+ bool ok = !overflows && this->check_range (base, array_size);
- hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
- (&this->debug_depth, "SANITIZE", this->blob, NULL,
- "check_array [%p..%p] (%d*%d=%ld bytes) in [%p..%p]",
- p, p + (record_size * len), record_size, len, (unsigned long) record_size * len,
- this->start, this->end);
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
+ p, p + (record_size * len), record_size, len, (unsigned int) array_size,
+ this->start, this->end,
+ overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
- return TRACE_RETURN (likely (!overflows && this->check_range (base, record_size * len)));
+ return likely (ok);
}
template <typename Type>
@@ -255,21 +262,20 @@ struct hb_sanitize_context_t
const char *p = (const char *) base;
this->edit_count++;
- hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace
- (&this->debug_depth, "SANITIZE", this->blob, NULL,
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
this->edit_count,
p, p + len, len,
this->start, this->end,
this->writable ? "GRANTED" : "DENIED");
- return TRACE_RETURN (this->writable);
+ return this->writable;
}
template <typename Type, typename ValueType>
- inline bool try_set (Type *obj, const ValueType &v) {
+ inline bool try_set (const Type *obj, const ValueType &v) {
if (this->may_edit (obj, obj->static_size)) {
- obj->set (v);
+ const_cast<Type *> (obj)->set (v);
return true;
}
return false;
@@ -289,7 +295,7 @@ template <typename Type>
struct Sanitizer
{
static hb_blob_t *sanitize (hb_blob_t *blob) {
- hb_sanitize_context_t c[1] = {{0}};
+ hb_sanitize_context_t c[1] = {{0, NULL, NULL, false, 0, NULL}};
bool sane;
/* TODO is_sane() stuff */
@@ -297,7 +303,7 @@ struct Sanitizer
c->init (blob);
retry:
- DEBUG_MSG_FUNC (SANITIZE, blob, "start");
+ DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
c->start_processing ();
@@ -311,13 +317,13 @@ struct Sanitizer
sane = t->sanitize (c);
if (sane) {
if (c->edit_count) {
- DEBUG_MSG_FUNC (SANITIZE, blob, "passed first round with %d edits; going for second round", c->edit_count);
+ DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
/* sanitize again to ensure no toe-stepping */
c->edit_count = 0;
sane = t->sanitize (c);
if (c->edit_count) {
- DEBUG_MSG_FUNC (SANITIZE, blob, "requested %d edits in second round; FAILLING", c->edit_count);
+ DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
sane = false;
}
}
@@ -330,7 +336,7 @@ struct Sanitizer
if (c->start) {
c->writable = true;
/* ok, we made it writable by relocating. try again */
- DEBUG_MSG_FUNC (SANITIZE, blob, "retry");
+ DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
goto retry;
}
}
@@ -338,7 +344,7 @@ struct Sanitizer
c->end_processing ();
- DEBUG_MSG_FUNC (SANITIZE, blob, sane ? "PASSED" : "FAILED");
+ DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
if (sane)
return blob;
else {
@@ -533,31 +539,55 @@ template <typename Type>
struct BEInt<Type, 2>
{
public:
- inline void set (Type i) { hb_be_uint16_put (v,i); }
- inline operator Type (void) const { return hb_be_uint16_get (v); }
- inline bool operator == (const BEInt<Type, 2>& o) const { return hb_be_uint16_eq (v, o.v); }
- inline bool operator != (const BEInt<Type, 2>& o) const { return !(*this == o); }
+ inline void set (Type V)
+ {
+ v[0] = (V >> 8) & 0xFF;
+ v[1] = (V ) & 0xFF;
+ }
+ inline operator Type (void) const
+ {
+ return (v[0] << 8)
+ + (v[1] );
+ }
private: uint8_t v[2];
};
template <typename Type>
-struct BEInt<Type, 4>
+struct BEInt<Type, 3>
{
public:
- inline void set (Type i) { hb_be_uint32_put (v,i); }
- inline operator Type (void) const { return hb_be_uint32_get (v); }
- inline bool operator == (const BEInt<Type, 4>& o) const { return hb_be_uint32_eq (v, o.v); }
- inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
- private: uint8_t v[4];
+ inline void set (Type V)
+ {
+ v[0] = (V >> 16) & 0xFF;
+ v[1] = (V >> 8) & 0xFF;
+ v[2] = (V ) & 0xFF;
+ }
+ inline operator Type (void) const
+ {
+ return (v[0] << 16)
+ + (v[1] << 8)
+ + (v[2] );
+ }
+ private: uint8_t v[3];
};
template <typename Type>
-struct BEInt<Type, 3>
+struct BEInt<Type, 4>
{
public:
- inline void set (Type i) { hb_be_uint24_put (v,i); }
- inline operator Type (void) const { return hb_be_uint24_get (v); }
- inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); }
- inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); }
- private: uint8_t v[3];
+ inline void set (Type V)
+ {
+ v[0] = (V >> 24) & 0xFF;
+ v[1] = (V >> 16) & 0xFF;
+ v[2] = (V >> 8) & 0xFF;
+ v[3] = (V ) & 0xFF;
+ }
+ inline operator Type (void) const
+ {
+ return (v[0] << 24)
+ + (v[1] << 16)
+ + (v[2] << 8)
+ + (v[3] );
+ }
+ private: uint8_t v[4];
};
/* Integer types in big-endian order and no alignment requirement */
@@ -566,12 +596,19 @@ struct IntType
{
inline void set (Type i) { v.set (i); }
inline operator Type(void) const { return v; }
- inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; }
- inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; }
+ inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
+ inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
- inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
- inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
- inline bool sanitize (hb_sanitize_context_t *c) {
+ inline int cmp (Type a) const
+ {
+ Type b = v;
+ if (sizeof (Type) < sizeof (int))
+ return (int) a - (int) b;
+ else
+ return a < b ? -1 : a == b ? 0 : +1;
+ }
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
TRACE_SANITIZE (this);
return TRACE_RETURN (likely (c->check_struct (this)));
}
@@ -598,7 +635,8 @@ typedef USHORT UFWORD;
* 1904. The value is represented as a signed 64-bit integer. */
struct LONGDATETIME
{
- inline bool sanitize (hb_sanitize_context_t *c) {
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
TRACE_SANITIZE (this);
return TRACE_RETURN (likely (c->check_struct (this)));
}
@@ -622,7 +660,10 @@ struct Tag : ULONG
DEFINE_NULL_DATA (Tag, " ");
/* Glyph index number, same as uint16 (length = 16 bits) */
-typedef USHORT GlyphID;
+struct GlyphID : USHORT {
+ static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); }
+ inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; }
+};
/* Script/language-system/feature index */
struct Index : USHORT {
@@ -671,7 +712,8 @@ struct FixedVersion
{
inline uint32_t to_int (void) const { return (major << 16) + minor; }
- inline bool sanitize (hb_sanitize_context_t *c) {
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this));
}
@@ -699,33 +741,35 @@ struct OffsetTo : Offset<OffsetType>
return StructAtOffset<Type> (base, offset);
}
- inline Type& serialize (hb_serialize_context_t *c, void *base)
+ inline Type& serialize (hb_serialize_context_t *c, const void *base)
{
Type *t = c->start_embed<Type> ();
this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
return *t;
}
- inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
unsigned int offset = *this;
if (unlikely (!offset)) return TRACE_RETURN (true);
- Type &obj = StructAtOffset<Type> (base, offset);
+ const Type &obj = StructAtOffset<Type> (base, offset);
return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c));
}
template <typename T>
- inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+ {
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
unsigned int offset = *this;
if (unlikely (!offset)) return TRACE_RETURN (true);
- Type &obj = StructAtOffset<Type> (base, offset);
+ const Type &obj = StructAtOffset<Type> (base, offset);
return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c));
}
/* Set the offset to Null */
- inline bool neuter (hb_sanitize_context_t *c) {
+ inline bool neuter (hb_sanitize_context_t *c) const {
return c->try_set (this, 0);
}
DEFINE_SIZE_STATIC (sizeof(OffsetType));
@@ -790,7 +834,8 @@ struct ArrayOf
return TRACE_RETURN (true);
}
- inline bool sanitize (hb_sanitize_context_t *c) {
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
@@ -805,7 +850,8 @@ struct ArrayOf
return TRACE_RETURN (true);
}
- inline bool sanitize (hb_sanitize_context_t *c, void *base) {
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
unsigned int count = len;
@@ -815,7 +861,8 @@ struct ArrayOf
return TRACE_RETURN (true);
}
template <typename T>
- inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) {
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+ {
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);
unsigned int count = len;
@@ -836,7 +883,8 @@ struct ArrayOf
}
private:
- inline bool sanitize_shallow (hb_sanitize_context_t *c) {
+ inline bool sanitize_shallow (hb_sanitize_context_t *c) const
+ {
TRACE_SANITIZE (this);
return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len));
}
@@ -862,12 +910,14 @@ struct OffsetListOf : OffsetArrayOf<Type>
return this+this->array[i];
}
- inline bool sanitize (hb_sanitize_context_t *c) {
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
TRACE_SANITIZE (this);
return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this));
}
template <typename T>
- inline bool sanitize (hb_sanitize_context_t *c, T user_data) {
+ inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
+ {
TRACE_SANITIZE (this);
return TRACE_RETURN (OffsetArrayOf<Type>::sanitize (c, this, user_data));
}
@@ -901,12 +951,14 @@ struct HeadlessArrayOf
return TRACE_RETURN (true);
}
- inline bool sanitize_shallow (hb_sanitize_context_t *c) {
+ inline bool sanitize_shallow (hb_sanitize_context_t *c) const
+ {
return c->check_struct (this)
&& c->check_array (this, Type::static_size, len);
}
- inline bool sanitize (hb_sanitize_context_t *c) {
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false);