Skip to content
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

Update fuzzer to newer GC spec regarding JS interop #4965

Merged
merged 13 commits into from
Aug 31, 2022
Merged

Update fuzzer to newer GC spec regarding JS interop #4965

merged 13 commits into from
Aug 31, 2022

Conversation

kripken
Copy link
Member

@kripken kripken commented Aug 24, 2022

Do not export functions that have types not allowed in the rules for
JS interop. Only very few GC types can be on the JS boundary atm.

@kripken kripken requested a review from tlively August 24, 2022 18:38
Comment on lines +563 to +564
bool validExportResults =
std::all_of(resultType.begin(), resultType.end(), validExportType);
Copy link
Member

Choose a reason for hiding this comment

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

I don't think non-nullable values are allowed in the return position, either.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, they do work in the fuzzer itself (we don't mind receiving such values, the problem is manufacturing them in order to send them), and I don't see errors in V8? It accepts e.g. (result (ref func)) on an export, and I'm not sure why it shouldn't?

Copy link
Member

Choose a reason for hiding this comment

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

This contradicts the draft document, which states, "Function parameters and results: only externref + funcref allowed." @jakobkummerow am I reading the intention there incorrectly?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ha, good question!

We've only partially implemented this (because we've allowed more so far, dating back to older guesses about what the JS API might allow, and wanted to be careful about causing breakage), so the fact that you're not getting errors currently isn't a reliable datapoint.

The quoted phrasing disallows non-nullable refs. The intention is that there will be no or absolutely minimal implicit checking at the boundary (for funcref we can't get around checking whether it's a function, but that ship has sailed; stringref can't get around a string check but is considered important enough to allow). To achieve that goal, it's sufficient if the result types of exported Wasm functions are restricted to being subtypes of funcref or externref or stringref, which in particular includes the non-nullable variants of these types. I don't feel strongly about how to resolve this:
(1) most strict option: require exactly funcref or externref or stringref, nothing else, for both parameters and results.
(2) slightly relaxed: only funcref or externref or stringref for parameters, optionally non-nullable results.
(3) maximally relaxed: parameters must be exactly funcref or externref or stringref, results must be subtypes of funcref or externref or stringref (which for the latter two is almost the same as option (2): it would also allow the respective none-type).

Notably none of these options has an impact on run-time performance, they're just minor details of static type checking behavior. I assume that for module producers it doesn't make a practical difference, in particular because of implicit upcasting for any return values (e.g. a function's return type could be relaxed from (result (ref $my_custom_func)) to (result funcref) without changing anything in the function's body).

I think I'm weakly leaning towards option (1) because I don't yet see compelling reasons for anything else, but I could be convinced otherwise. WDYT?

Note 1: option (3) has some analogy to function subtyping: parameters must be "contravariant", i.e. must be supertypes of funcref or externref. Since these are top types, their only supertypes are themselves. Results must be "covariant", i.e. subtypes of F/E. Stringrefs break this analogy though: we don't want to allow anyref parameters, even though that's (most likely) a supertype of stringref.
Note 2: in all statements about required types, there's an implicit "...or one of the traditional Wasm types i32 etc." that's left out for brevity.

@kripken
Copy link
Member Author

kripken commented Aug 31, 2022

There may be more to discuss here, but what do you think about landing this to fix fuzzing @tlively ?

Copy link
Member

@tlively tlively left a comment

Choose a reason for hiding this comment

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

Let's at least add a comment on validExportResults mentioning that the intended behavior isn't quite settled.

@kripken kripken enabled auto-merge (squash) August 31, 2022 16:04
@kripken kripken merged commit 1fa64bf into main Aug 31, 2022
@kripken kripken deleted the fuzz.anyref branch August 31, 2022 16:53
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.

3 participants