#ifndef HB_SANITIZE_MAX_OPS_MAX
#define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF
#endif
+#ifndef HB_SANITIZE_MAX_SUTABLES
+#define HB_SANITIZE_MAX_SUTABLES 0x4000
+#endif
struct hb_sanitize_context_t :
hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
hb_sanitize_context_t () :
debug_depth (0),
start (nullptr), end (nullptr),
- max_ops (0),
+ max_ops (0), max_subtables (0),
writable (false), edit_count (0),
blob (nullptr),
num_glyphs (65536),
static return_t no_dispatch_return_value () { return false; }
bool stop_sublookup_iteration (const return_t r) const { return !r; }
+ bool visit_subtables (unsigned count)
+ {
+ max_subtables += count;
+ return max_subtables < HB_SANITIZE_MAX_SUTABLES;
+ }
+
private:
template <typename T, typename ...Ts> auto
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
void start_processing ()
{
reset_object ();
- this->max_ops = hb_max ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
- (unsigned) HB_SANITIZE_MAX_OPS_MIN);
+ if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR)))
+ this->max_ops = HB_SANITIZE_MAX_OPS_MAX;
+ else
+ this->max_ops = hb_clamp ((unsigned) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+ (unsigned) HB_SANITIZE_MAX_OPS_MIN,
+ (unsigned) HB_SANITIZE_MAX_OPS_MAX);
this->edit_count = 0;
this->debug_depth = 0;
mutable unsigned int debug_depth;
const char *start, *end;
- mutable int max_ops;
+ mutable int max_ops, max_subtables;
private:
bool writable;
unsigned int edit_count;