diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh index 03476faba..f70084b2f 100644 --- a/src/hb-ot-color-colr-table.hh +++ b/src/hb-ot-color-colr-table.hh @@ -985,7 +985,7 @@ struct ClipList for (const hb_codepoint_t _ : gids.iter ()) { if (_ == start_gid) continue; - + offset = gid_offset_map.get (_); if (_ == prev_gid + 1 && offset == prev_offset) { @@ -1027,7 +1027,7 @@ struct ClipList const hb_set_t& glyphset = *c->plan->_glyphset; const hb_map_t &glyph_map = *c->plan->glyph_map; - + hb_map_t new_gid_offset_map; hb_set_t new_gids; for (const ClipRecord& record : clips.iter ()) @@ -1062,6 +1062,51 @@ struct ClipList struct Paint { + + template + bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const + { + TRACE_SANITIZE (this); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + if (unlikely (!c->check_start_recursion ())) return_trace (c->no_dispatch_return_value ()); + + switch (u.format) { + case 1: return_trace (c->end_recursion (c->dispatch (u.paintformat1, std::forward (ds)...))); + case 2: return_trace (c->end_recursion (c->dispatch (u.paintformat2, std::forward (ds)...))); + case 3: return_trace (c->end_recursion (c->dispatch (u.paintformat3, std::forward (ds)...))); + case 4: return_trace (c->end_recursion (c->dispatch (u.paintformat4, std::forward (ds)...))); + case 5: return_trace (c->end_recursion (c->dispatch (u.paintformat5, std::forward (ds)...))); + case 6: return_trace (c->end_recursion (c->dispatch (u.paintformat6, std::forward (ds)...))); + case 7: return_trace (c->end_recursion (c->dispatch (u.paintformat7, std::forward (ds)...))); + case 8: return_trace (c->end_recursion (c->dispatch (u.paintformat8, std::forward (ds)...))); + case 9: return_trace (c->end_recursion (c->dispatch (u.paintformat9, std::forward (ds)...))); + case 10: return_trace (c->end_recursion (c->dispatch (u.paintformat10, std::forward (ds)...))); + case 11: return_trace (c->end_recursion (c->dispatch (u.paintformat11, std::forward (ds)...))); + case 12: return_trace (c->end_recursion (c->dispatch (u.paintformat12, std::forward (ds)...))); + case 13: return_trace (c->end_recursion (c->dispatch (u.paintformat13, std::forward (ds)...))); + case 14: return_trace (c->end_recursion (c->dispatch (u.paintformat14, std::forward (ds)...))); + case 15: return_trace (c->end_recursion (c->dispatch (u.paintformat15, std::forward (ds)...))); + case 16: return_trace (c->end_recursion (c->dispatch (u.paintformat16, std::forward (ds)...))); + case 17: return_trace (c->end_recursion (c->dispatch (u.paintformat17, std::forward (ds)...))); + case 18: return_trace (c->end_recursion (c->dispatch (u.paintformat18, std::forward (ds)...))); + case 19: return_trace (c->end_recursion (c->dispatch (u.paintformat19, std::forward (ds)...))); + case 20: return_trace (c->end_recursion (c->dispatch (u.paintformat20, std::forward (ds)...))); + case 21: return_trace (c->end_recursion (c->dispatch (u.paintformat21, std::forward (ds)...))); + case 22: return_trace (c->end_recursion (c->dispatch (u.paintformat22, std::forward (ds)...))); + case 23: return_trace (c->end_recursion (c->dispatch (u.paintformat23, std::forward (ds)...))); + case 24: return_trace (c->end_recursion (c->dispatch (u.paintformat24, std::forward (ds)...))); + case 25: return_trace (c->end_recursion (c->dispatch (u.paintformat25, std::forward (ds)...))); + case 26: return_trace (c->end_recursion (c->dispatch (u.paintformat26, std::forward (ds)...))); + case 27: return_trace (c->end_recursion (c->dispatch (u.paintformat27, std::forward (ds)...))); + case 28: return_trace (c->end_recursion (c->dispatch (u.paintformat28, std::forward (ds)...))); + case 29: return_trace (c->end_recursion (c->dispatch (u.paintformat29, std::forward (ds)...))); + case 30: return_trace (c->end_recursion (c->dispatch (u.paintformat30, std::forward (ds)...))); + case 31: return_trace (c->end_recursion (c->dispatch (u.paintformat31, std::forward (ds)...))); + case 32: return_trace (c->end_recursion (c->dispatch (u.paintformat32, std::forward (ds)...))); + default:return_trace (c->end_recursion (c->default_return_value ())); + } + } + template typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { diff --git a/src/hb-sanitize.hh b/src/hb-sanitize.hh index d0f2fa585..faeb2aa49 100644 --- a/src/hb-sanitize.hh +++ b/src/hb-sanitize.hh @@ -117,17 +117,16 @@ #define HB_SANITIZE_MAX_SUBTABLES 0x4000 #endif #ifndef HB_SANITIZE_MAX_DEPTH -#define HB_SANITIZE_MAX_DEPTH 5000 +#define HB_SANITIZE_MAX_DEPTH 2500 #endif - struct hb_sanitize_context_t : hb_dispatch_context_t { hb_sanitize_context_t () : - max_depth (0), start (nullptr), end (nullptr), max_ops (0), max_subtables (0), + recursion_depth (0), writable (false), edit_count (0), blob (nullptr), num_glyphs (65536), @@ -148,7 +147,6 @@ struct hb_sanitize_context_t : } private: - int max_depth; template auto _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN ( obj.sanitize (this, std::forward (ds)...) ) @@ -158,9 +156,8 @@ struct hb_sanitize_context_t : public: template auto dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN - ( --max_depth > 0 - ? _dispatch (obj, hb_prioritize, std::forward (ds)...) && max_depth++ - : false ) + ( _dispatch (obj, hb_prioritize, std::forward (ds)...) ) + void init (hb_blob_t *b) { @@ -204,7 +201,6 @@ struct hb_sanitize_context_t : void start_processing () { reset_object (); - this->max_depth = HB_SANITIZE_MAX_DEPTH; if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR))) this->max_ops = HB_SANITIZE_MAX_OPS_MAX; else @@ -213,6 +209,7 @@ struct hb_sanitize_context_t : (unsigned) HB_SANITIZE_MAX_OPS_MAX); this->edit_count = 0; this->debug_depth = 0; + this->recursion_depth = 0; DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1, "start [%p..%p] (%lu bytes)", @@ -286,6 +283,18 @@ struct hb_sanitize_context_t : return this->check_range (base, a, b, hb_static_size (T)); } + bool check_start_recursion () + { + if (unlikely (recursion_depth >= HB_SANITIZE_MAX_DEPTH)) return false; + return ++recursion_depth; + } + + bool end_recursion (bool result) + { + recursion_depth--; + return result; + } + template bool check_struct (const Type *obj) const { return likely (this->check_range (obj, obj->min_size)); } @@ -397,6 +406,7 @@ struct hb_sanitize_context_t : const char *start, *end; mutable int max_ops, max_subtables; private: + int recursion_depth; bool writable; unsigned int edit_count; hb_blob_t *blob; diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-draw-fuzzer-4856957815619584 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-draw-fuzzer-4856957815619584 new file mode 100644 index 000000000..9adb77914 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-draw-fuzzer-4856957815619584 differ