Fix use-after-free resolving ref types after instruction recovery - #2823
Fix use-after-free resolving ref types after instruction recovery#2823aizu-m wants to merge 2 commits into
Conversation
|
Out of interest @aizu-m, why are you so interested in fixed these types of bugs in wabt? |
zherczeg
left a comment
There was a problem hiding this comment.
Are both changes covered by a single test?
| void WastParser::TruncateResolveLists(size_t ref_types_size, | ||
| size_t type_vectors_size, | ||
| size_t funcs_size) { | ||
| resolve_ref_types_.erase(resolve_ref_types_.begin() + ref_types_size, |
There was a problem hiding this comment.
what about using vector::resize?
There was a problem hiding this comment.
Done, switched all three to resize (needed to add defaulted constructors to the resolve structs since they only had value ctors). Reads better.
|
Unrelated to this PR, but it is also a good question how can we manually maintain these reverts. How can we get some info that it is missing somewhere. |
|
@zherczeg on the test: before, only the ParseInstrList path was hit (the two bare block/loop funcs). The ParseExprList branch was untouched, so I added a folded case to the same test: @sbc100 mostly curiosity plus it's good practice. I've been fuzzing the wat/binary front-ends (libFuzzer + ASan/UBSan) and these parser recovery paths keep turning up reachable use-after-frees, so I've been sending fixes as I minimise them. This one fell out of the same corpus as #2805. |
|
LGTM form my side, but lets wait @sbc100 because he might give us insight about the original design, which is a bit strange for me. |
|
#2824 landed while this was waiting and fixes the same bug a different way. It makes ParseInstrList/ParseExprList return Error so ParseModuleField's #2805 rollback runs, rather than truncating the resolve lists inline like this PR does. I checked both reproducers from here against current main under a debug+ASan build. The bare block/loop case and the folded So this one is now redundant, which is also why it conflicts on the same lines. Happy to close it. Say the word if you'd rather I rebase, but I don't think there's anything left for it to do. |
a block/loop/if whose signature names a reference type defers a resolution pointing into it and is freed when it fails to parse, but ParseInstrList recovers from that failure so the enclosing func still parses and the #2805 field-level truncation never runs, leaving the resolution to dereference the freed instruction; truncate the resolve lists on the instruction recovery path (ParseInstrList/ParseExprList) too, the same way ParseModuleField already does on a failed field.