From 4e2f409bce77b97de2d098365977beeeb4447b1e Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Mon, 31 Jan 2022 12:20:32 -0800 Subject: [PATCH] [subset] Don't hold references to members of the active_glyph_stack. These references may get invalidated after the vector for the stack is resized. Fixes: https://oss-fuzz.com/testcase-detail/5422577634377728 --- src/hb-ot-layout-gsubgpos.hh | 54 +++++++++++------- ...inimized-hb-subset-fuzzer-5422577634377728 | Bin 0 -> 1700 bytes 2 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5422577634377728 diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 51daf2c02..65de131f8 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -132,6 +132,13 @@ struct hb_closure_context_t : return false; } + const hb_set_t& previous_parent_active_glyphs () { + if (active_glyphs_stack.length <= 1) + return *glyphs; + + return active_glyphs_stack[active_glyphs_stack.length - 2]; + } + const hb_set_t& parent_active_glyphs () { if (!active_glyphs_stack) @@ -1864,9 +1871,9 @@ struct ContextFormat1 void closure (hb_closure_context_t *c) const { - const hb_set_t* parent_active_glyphs = &c->parent_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (parent_active_glyphs, - &c->push_cur_active_glyphs ()); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); struct ContextClosureLookupContext lookup_context = { {intersects_glyph, intersected_glyph}, @@ -1875,7 +1882,9 @@ struct ContextFormat1 }; + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len)) - | hb_filter (parent_active_glyphs, hb_first) + | hb_filter ([&] (hb_codepoint_t _) { + return c->previous_parent_active_glyphs ().has (_); + }, hb_first) | hb_map ([&](const hb_pair_t _) { return hb_pair_t (_.first, this+ruleSet[_.second]); }) | hb_apply ([&] (const hb_pair_t& _) { _.second.closure (c, _.first, lookup_context); }) ; @@ -2028,9 +2037,9 @@ struct ContextFormat2 if (!(this+coverage).intersects (c->glyphs)) return; - const hb_set_t* parent_active_glyphs = &c->parent_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (parent_active_glyphs, - &c->push_cur_active_glyphs ()); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); const ClassDef &class_def = this+classDef; @@ -2224,9 +2233,10 @@ struct ContextFormat3 if (!(this+coverageZ[0]).intersects (c->glyphs)) return; - const hb_set_t* parent_active_glyphs = &c->parent_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (parent_active_glyphs, - &c->push_cur_active_glyphs ()); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); + const LookupRecord *lookupRecord = &StructAfter (coverageZ.as_array (glyphCount)); struct ContextClosureLookupContext lookup_context = { @@ -2859,9 +2869,9 @@ struct ChainContextFormat1 void closure (hb_closure_context_t *c) const { - const hb_set_t* parent_active_glyphs = &c->parent_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (parent_active_glyphs, - &c->push_cur_active_glyphs ()); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); struct ChainContextClosureLookupContext lookup_context = { {intersects_glyph, intersected_glyph}, @@ -2870,7 +2880,9 @@ struct ChainContextFormat1 }; + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len)) - | hb_filter (parent_active_glyphs, hb_first) + | hb_filter ([&] (hb_codepoint_t _) { + return c->previous_parent_active_glyphs ().has (_); + }, hb_first) | hb_map ([&](const hb_pair_t _) { return hb_pair_t (_.first, this+ruleSet[_.second]); }) | hb_apply ([&] (const hb_pair_t& _) { _.second.closure (c, _.first, lookup_context); }) ; @@ -3024,9 +3036,10 @@ struct ChainContextFormat2 if (!(this+coverage).intersects (c->glyphs)) return; - const hb_set_t* parent_active_glyphs = &c->parent_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (parent_active_glyphs, - &c->push_cur_active_glyphs ()); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); + const ClassDef &backtrack_class_def = this+backtrackClassDef; const ClassDef &input_class_def = this+inputClassDef; @@ -3278,9 +3291,10 @@ struct ChainContextFormat3 if (!(this+input[0]).intersects (c->glyphs)) return; - const hb_set_t* parent_active_glyphs = &c->parent_active_glyphs (); - get_coverage ().intersected_coverage_glyphs (parent_active_glyphs, - &c->push_cur_active_glyphs ()); + hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs (); + get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (), + cur_active_glyphs); + const Array16OfOffset16To &lookahead = StructAfter> (input); const Array16Of &lookup = StructAfter> (lookahead); diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5422577634377728 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5422577634377728 new file mode 100644 index 0000000000000000000000000000000000000000..aba40f13a23da14269e308e39a22ba012324fa2f GIT binary patch literal 1700 zcmc&!J4ypl6g@8)O&BBw2`Ev*LHsl#Hg3Si#xA&k5DS}N5DT%guy7SF!_Ex|F2w~{ zjrY8HkC`!}5Q%um-23K!&i%Y0Z~!`44n}10P|>Hu^Ai~W2kBp?^fB%m>O zZcMOIfD{89zb7`q)9pQk(H?el}7J%@P{Syf34VN>UEQ>1@{_Wslmd{VGrFjC|rN ztMG|75}F~$*z|FT!={z+@SGMCamY10qOE#@X@Ne@Om^ZEI?xx{N<<(+Yk9pP%$v literal 0 HcmV?d00001