[subset] speed up add_gid_and_children and adjust op limit.

Fix for fuzzer timeout: https://oss-fuzz.com/testcase-detail/5001604901240832.

- Operation limit is per glyph, so 100,000 should still be far more than needed.
- Switches from for(...) to while(...) loop for iteration. for(...) calls it.end() which in this case triggers a complete iteration.
- Cache CompositeGlyph size in the iterator to avoid needing to recalculate it.
This commit is contained in:
Garret Rieger 2021-08-11 16:20:05 -07:00 committed by Behdad Esfahbod
parent c45d2a9c9d
commit c0f3af91b8
2 changed files with 34 additions and 14 deletions

View File

@ -46,7 +46,7 @@ namespace OT {
#define HB_OT_TAG_loca HB_TAG('l','o','c','a') #define HB_OT_TAG_loca HB_TAG('l','o','c','a')
#ifndef HB_MAX_COMPOSITE_OPERATIONS #ifndef HB_MAX_COMPOSITE_OPERATIONS
#define HB_MAX_COMPOSITE_OPERATIONS 1000000 #define HB_MAX_COMPOSITE_OPERATIONS 100000
#endif #endif
@ -397,9 +397,12 @@ struct glyf
{ {
typedef const CompositeGlyphChain *__item_t__; typedef const CompositeGlyphChain *__item_t__;
composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) : composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
glyph (glyph_), current (current_) glyph (glyph_), current (nullptr), current_size (0)
{ if (!check_range (current)) current = nullptr; } {
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {} set_next (current_);
}
composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
const CompositeGlyphChain &__item__ () const { return *current; } const CompositeGlyphChain &__item__ () const { return *current; }
bool __more__ () const { return current; } bool __more__ () const { return current; }
@ -407,23 +410,36 @@ struct glyf
{ {
if (!current->has_more ()) { current = nullptr; return; } if (!current->has_more ()) { current = nullptr; return; }
const CompositeGlyphChain *possible = &StructAfter<CompositeGlyphChain, set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
CompositeGlyphChain> (*current);
if (!check_range (possible)) { current = nullptr; return; }
current = possible;
} }
bool operator != (const composite_iter_t& o) const bool operator != (const composite_iter_t& o) const
{ return glyph != o.glyph || current != o.current; } { return glyph != o.glyph || current != o.current; }
bool check_range (const CompositeGlyphChain *composite) const
void set_next (const CompositeGlyphChain *composite)
{ {
return glyph.check_range (composite, CompositeGlyphChain::min_size) if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
&& glyph.check_range (composite, composite->get_size ()); {
current = nullptr;
current_size = 0;
return;
}
unsigned size = composite->get_size ();
if (!glyph.check_range (composite, size))
{
current = nullptr;
current_size = 0;
return;
}
current = composite;
current_size = size;
} }
private: private:
hb_bytes_t glyph; hb_bytes_t glyph;
__item_t__ current; __item_t__ current;
unsigned current_size;
}; };
enum phantom_point_index_t enum phantom_point_index_t
@ -1098,9 +1114,13 @@ struct glyf
gids_to_retain->add (gid); gids_to_retain->add (gid);
for (auto &item : glyph_for_gid (gid).get_composite_iterator ()) auto it = glyph_for_gid (gid).get_composite_iterator ();
while (it)
{
auto item = *(it++);
operation_count += operation_count +=
add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count); add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
}
return operation_count; return operation_count;
} }