From 2d940946d5af0e3869a2324b6e36ca8ea3698c48 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 30 Jan 2019 16:03:16 -0800 Subject: [PATCH] [iter] Fix mystery crash Fuzzer caught it: ==14==ERROR: AddressSanitizer: stack-use-after-return on address 0x7fca2ed7a3e0 at pc 0x0000006057aa bp 0x7ffc3290f1d0 sp 0x7ffc3290f1c8 READ of size 4 at 0x7fca2ed7a3e0 thread T0 SCARINESS: 55 (4-byte-read-stack-use-after-return) #0 0x6057a9 in OT::SingleSubstFormat2::subset(hb_subset_context_t*) const /src/harfbuzz/src/./hb-ot-layout-gsub-table.hh:194:40 #1 0x5ff921 in hb_subset_context_t::return_t OT::SingleSubst::dispatch(hb_subset_context_t*) const /src/harfbuzz/src/./hb-ot-layout-gsub-table.hh:256:13 I can't reproduce locally, but many of the bots are failing because of this as well. It's a pity that operator-> must return pointer. Ugh. Why?! --- src/hb-iter.hh | 4 ++++ src/hb-ot-layout-gsub-table.hh | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hb-iter.hh b/src/hb-iter.hh index 105379eea..290e6af3e 100644 --- a/src/hb-iter.hh +++ b/src/hb-iter.hh @@ -71,6 +71,10 @@ struct hb_iter_t iter_t operator + () const { return *thiz(); } explicit_operator bool () const { return thiz()->__more__ (); } unsigned len () const { return thiz()->__len__ (); } + /* The following can only be enabled if item_t is reference type. Otherwise + * it will be returning pointer to temporary rvalue. */ + template hb_remove_reference (item_t)* operator -> () const { return hb_addressof (**thiz()); } item_t operator * () const { return thiz()->__item__ (); } item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); } diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 518afaac5..dd6f017b8 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -191,8 +191,8 @@ struct SingleSubstFormat2 for (auto it = hb_zip (this+coverage, substitute) | hb_filter (glyphset, hb_first); it; ++it) { - from.push ()->set (glyph_map[it->first]); - to.push ()->set (glyph_map[it->second]); + from.push ()->set (glyph_map[(*it).first]); + to.push ()->set (glyph_map[(*it).second]); } c->serializer->propagate_error (from, to); SingleSubst_serialize (c->serializer, from, to);