From 2d54c34680fd22e195eb6bd9e87c25a94e9a4b8b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 28 Jul 2021 18:20:53 -0600 Subject: [PATCH] [subset/VarStore] Fix OOM in fuzzer test The test in question is the one added in c68a00b92eb62fdc79f9a2bd1fc7a6acc24a3602. Culprit is that it's allocating lots of memory because of region_indices that are out-of-range anyway. So, try to filter those out first. --- src/hb-ot-layout-common.hh | 28 ++++++++++++++++++---------- src/hb-set.hh | 2 +- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 6f42a0122..26cc2a4df 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -2528,7 +2528,7 @@ struct VarRegionList if (unlikely (hb_unsigned_mul_overflows (axisCount * regionCount, VarRegionAxis::static_size))) return_trace (false); if (unlikely (!c->extend (this))) return_trace (false); - unsigned int region_count = src->get_region_count (); + unsigned int region_count = src->regionCount; for (unsigned int r = 0; r < regionCount; r++) { unsigned int backward = region_map.backward (r); @@ -2540,11 +2540,11 @@ struct VarRegionList } unsigned int get_size () const { return min_size + VarRegionAxis::static_size * axisCount * regionCount; } - unsigned int get_region_count () const { return regionCount; } - protected: + public: HBUINT16 axisCount; HBUINT16 regionCount; + protected: UnsizedArrayOf axesZ; public: @@ -2683,16 +2683,16 @@ struct VarData return_trace (true); } - void collect_region_refs (hb_inc_bimap_t ®ion_map, const hb_inc_bimap_t &inner_map) const + void collect_region_refs (hb_set_t ®ion_indices, const hb_inc_bimap_t &inner_map) const { for (unsigned int r = 0; r < regionIndices.len; r++) { unsigned int region = regionIndices[r]; - if (region_map.has (region)) continue; + if (region_indices.has (region)) continue; for (unsigned int i = 0; i < inner_map.get_next_value (); i++) if (get_item_delta (inner_map.backward (i), r) != 0) { - region_map.add (region); + region_indices.add (region); break; } } @@ -2787,14 +2787,22 @@ struct VariationStore format = 1; - hb_inc_bimap_t region_map; + const auto &src_regions = src+src->regions; + + hb_set_t region_indices; for (unsigned int i = 0; i < inner_maps.length; i++) - (src+src->dataSets[i]).collect_region_refs (region_map, inner_maps[i]); + (src+src->dataSets[i]).collect_region_refs (region_indices, inner_maps[i]); + region_indices.del_range ((src_regions).regionCount, region_indices.get_max ()); + + /* TODO use constructor when our data-structures support that. */ + hb_inc_bimap_t region_map; + + hb_iter (region_indices) + | hb_apply ([®ion_map] (unsigned _) { region_map.add(_); }) + ; if (region_map.in_error()) return_trace (false); - region_map.sort (); - if (unlikely (!regions.serialize_serialize (c, &(src+src->regions), region_map))) + if (unlikely (!regions.serialize_serialize (c, &src_regions, region_map))) return_trace (false); dataSets.len = set_count; diff --git a/src/hb-set.hh b/src/hb-set.hh index 5688619e8..8bb7f9f0b 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -427,7 +427,7 @@ struct hb_set_t { /* TODO perform op even if !successful. */ if (unlikely (!successful)) return; - if (unlikely (a > b || a == INVALID || b == INVALID)) return; + if (unlikely (a > b || a == INVALID)) return; dirty (); unsigned int ma = get_major (a); unsigned int mb = get_major (b);