summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh120
1 files changed, 110 insertions, 10 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
index eb907c6b2a..408649c768 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
@@ -122,17 +122,22 @@ struct hb_sanitize_context_t :
{
hb_sanitize_context_t () :
start (nullptr), end (nullptr),
+ length (0),
max_ops (0), max_subtables (0),
recursion_depth (0),
writable (false), edit_count (0),
blob (nullptr),
num_glyphs (65536),
- num_glyphs_set (false) {}
+ num_glyphs_set (false),
+ lazy_some_gpos (false) {}
const char *get_name () { return "SANITIZE"; }
template <typename T, typename F>
bool may_dispatch (const T *obj HB_UNUSED, const F *format)
- { return format->sanitize (this); }
+ {
+ return format->sanitize (this) &&
+ hb_barrier ();
+ }
static return_t default_return_value () { return true; }
static return_t no_dispatch_return_value () { return false; }
bool stop_sublookup_iteration (const return_t r) const { return !r; }
@@ -155,6 +160,19 @@ struct hb_sanitize_context_t :
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
+ hb_sanitize_context_t (hb_blob_t *b) : hb_sanitize_context_t ()
+ {
+ init (b);
+
+ if (blob)
+ start_processing ();
+ }
+
+ ~hb_sanitize_context_t ()
+ {
+ if (blob)
+ end_processing ();
+ }
void init (hb_blob_t *b)
{
@@ -180,11 +198,15 @@ struct hb_sanitize_context_t :
const char *obj_start = (const char *) obj;
if (unlikely (obj_start < this->start || this->end <= obj_start))
+ {
this->start = this->end = nullptr;
+ this->length = 0;
+ }
else
{
this->start = obj_start;
this->end = obj_start + hb_min (size_t (this->end - obj_start), obj->get_size ());
+ this->length = this->end - this->start;
}
}
@@ -192,6 +214,7 @@ struct hb_sanitize_context_t :
{
this->start = this->blob->data;
this->end = this->start + this->blob->length;
+ this->length = this->end - this->start;
assert (this->start <= this->end); /* Must not overflow. */
}
@@ -224,19 +247,34 @@ struct hb_sanitize_context_t :
hb_blob_destroy (this->blob);
this->blob = nullptr;
this->start = this->end = nullptr;
+ this->length = 0;
}
unsigned get_edit_count () { return edit_count; }
+
+ bool check_ops(unsigned count)
+ {
+ /* Avoid underflow */
+ if (unlikely (this->max_ops < 0 || count >= (unsigned) this->max_ops))
+ {
+ this->max_ops = -1;
+ return false;
+ }
+ this->max_ops -= (int) count;
+ return true;
+ }
+
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool check_range (const void *base,
unsigned int len) const
{
const char *p = (const char *) base;
- bool ok = !len ||
- (this->start <= p &&
- p <= this->end &&
- (unsigned int) (this->end - p) >= len &&
- (this->max_ops -= len) > 0);
+ bool ok = (uintptr_t) (p - this->start) <= this->length &&
+ (unsigned int) (this->end - p) >= len &&
+ ((this->max_ops -= len) > 0);
DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
"check_range [%p..%p]"
@@ -247,6 +285,43 @@ struct hb_sanitize_context_t :
return likely (ok);
}
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
+ bool check_range_fast (const void *base,
+ unsigned int len) const
+ {
+ const char *p = (const char *) base;
+ bool ok = ((uintptr_t) (p - this->start) <= this->length &&
+ (unsigned int) (this->end - p) >= len);
+
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "check_range_fast [%p..%p]"
+ " (%u bytes) in [%p..%p] -> %s",
+ p, p + len, len,
+ this->start, this->end,
+ ok ? "OK" : "OUT-OF-RANGE");
+
+ return likely (ok);
+ }
+
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
+ bool check_point (const void *base) const
+ {
+ const char *p = (const char *) base;
+ bool ok = (uintptr_t) (p - this->start) <= this->length;
+
+ DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+ "check_point [%p]"
+ " in [%p..%p] -> %s",
+ p,
+ this->start, this->end,
+ ok ? "OK" : "OUT-OF-RANGE");
+
+ return likely (ok);
+ }
template <typename T>
bool check_range (const T *base,
@@ -270,6 +345,20 @@ struct hb_sanitize_context_t :
}
template <typename T>
+ HB_ALWAYS_INLINE
+ bool check_array_sized (const T *base, unsigned int len, unsigned len_size) const
+ {
+ if (len_size >= 4)
+ {
+ if (unlikely (hb_unsigned_mul_overflows (len, hb_static_size (T), &len)))
+ return false;
+ }
+ else
+ len = len * hb_static_size (T);
+ return this->check_range (base, len);
+ }
+
+ template <typename T>
bool check_array (const T *base, unsigned int len) const
{
return this->check_range (base, len, hb_static_size (T));
@@ -280,7 +369,7 @@ struct hb_sanitize_context_t :
unsigned int a,
unsigned int b) const
{
- return this->check_range (base, a, b, hb_static_size (T));
+ return this->check_range (base, hb_static_size (T), a, b);
}
bool check_start_recursion (int max_depth)
@@ -296,8 +385,16 @@ struct hb_sanitize_context_t :
}
template <typename Type>
+#ifndef HB_OPTIMIZE_SIZE
+ HB_ALWAYS_INLINE
+#endif
bool check_struct (const Type *obj) const
- { return likely (this->check_range (obj, obj->min_size)); }
+ {
+ if (sizeof (uintptr_t) == sizeof (uint32_t))
+ return likely (this->check_range_fast (obj, obj->min_size));
+ else
+ return likely (this->check_point ((const char *) obj + obj->min_size));
+ }
bool may_edit (const void *base, unsigned int len)
{
@@ -359,7 +456,7 @@ struct hb_sanitize_context_t :
edit_count = 0;
sane = t->sanitize (this);
if (edit_count) {
- DEBUG_MSG_FUNC (SANITIZE, start, "requested %u edits in second round; FAILLING", edit_count);
+ DEBUG_MSG_FUNC (SANITIZE, start, "requested %u edits in second round; FAILING", edit_count);
sane = false;
}
}
@@ -404,6 +501,7 @@ struct hb_sanitize_context_t :
}
const char *start, *end;
+ unsigned length;
mutable int max_ops, max_subtables;
private:
int recursion_depth;
@@ -412,6 +510,8 @@ struct hb_sanitize_context_t :
hb_blob_t *blob;
unsigned int num_glyphs;
bool num_glyphs_set;
+ public:
+ bool lazy_some_gpos;
};
struct hb_sanitize_with_object_t