Skip to content

Do not emit recursion groups without GC enabled #4738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 18, 2022
Merged

Do not emit recursion groups without GC enabled #4738

merged 5 commits into from
Jun 18, 2022

Conversation

tlively
Copy link
Member

@tlively tlively commented Jun 17, 2022

We emit nominal types as a single large recursion group, but this produces
invalid modules when --nominal or --hybrid was used without GC enabled. Fix the
bug by always emitting types as though they were structural (i.e. without
recursion groups) when GC is not enabled.

Fixes #4723.

We emit nominal types as a single large recursion group, but this produces
invalid modules when --nominal or --hybrid was used without GC enabled. Fix the
bug by always emitting types as though they were structural (i.e. without
recursion groups) when GC is not enabled.
@tlively
Copy link
Member Author

tlively commented Jun 17, 2022

Current dependencies on/for this PR:

This comment was auto-generated by Graphite.

@tlively tlively marked this pull request as ready for review June 17, 2022 16:42
@tlively tlively requested a review from kripken June 17, 2022 16:42
@@ -242,7 +247,7 @@ void WasmBinaryWriter::writeTypes() {
BYN_TRACE("== writeTypes\n");
auto start = startSection(BinaryConsts::Section::Type);
o << U32LEB(numGroups);
if (getTypeSystem() == TypeSystem::Nominal) {
if (typeSystem == TypeSystem::Nominal) {
// The nominal recursion group contains every type.
o << S32LEB(BinaryConsts::EncodedType::Rec)
<< U32LEB(indexedTypes.types.size());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you need to do something to avoid new line 265 from being reached? Or is that handled by getRecGroup always returning the same?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For --nominal, it all works out because the rec groups all have size 1. For --hybrid it all works because the MVP function types will also have rec group size 1, unless the input had rec groups. I don't think we have any validation that rec groups are only allowed when GC is enabled, but that seems like a separate problem.

;; RUN: wasm-opt %s --nominal --disable-gc -g -o %t.wasm

;; We should not get any recursion groups even though we used --nominal
;; RUN: wasm-opt %t.wasm --hybrid -all -S -o - | filecheck %s
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
;; RUN: wasm-opt %t.wasm --hybrid -all -S -o - | filecheck %s
;; RUN: wasm-opt %t.wasm -S -o - | filecheck %s

I think it's better to test non-hybrid, and without -all, so that we are testing the default mode. That way this would test emitting with nominal and reading with no flags, which is what the fuzzer does. And the last step is closest to what users would do. The test then verifies we can load without erroring.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --hybrid is load-bearing here. Without it, we would just ignore any rec groups in the binary and the test would pass even with the bug present. -all similarly might be necessary to allow any rec groups in the binary to reach the output so that the test fails correctly. I'll mention this in the comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, but it errors if rec groups are present but gc is disabled - that's the original error that led to this PR? I just want to make sure we have testing for that specifically. How about testing both paths?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, It's wasm2c that errors in the presence of recursion groups, not binaryen.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Binaryen errors too:

(module
  (func $foo)
)
$ wasm-opt -all --nominal a.wat -o a.wasm
warning: no passes specified, not doing any work
$ bin/wasm-opt a.wasm
[parse exception: Recursion groups not allowed with equirecursive typing (at 0:13)]
Fatal: error parsing wasm

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I added another run line that tests that we don't get a failure loading the module with the default flags.

@tlively tlively merged commit bab2105 into main Jun 18, 2022
@tlively tlively deleted the nominal-no-gc branch June 18, 2022 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

fuzz_opt fail due to parsing / validating issue in wasm2c
2 participants