Closed
Bug 1479794
Opened 7 years ago
Closed 7 years ago
Regularize wasm globals and functions so that we don't expose module-internal struct types
Categories
(Core :: JavaScript: WebAssembly, enhancement, P3)
Core
JavaScript: WebAssembly
Tracking
()
RESOLVED
FIXED
mozilla63
Tracking | Status | |
---|---|---|
firefox63 | --- | fixed |
People
(Reporter: lth, Assigned: lth)
References
Details
Attachments
(1 file, 2 obsolete files)
21.89 KB,
patch
|
luke
:
review+
bbouvier
:
feedback+
|
Details | Diff | Splinter Review |
We need a small amount of cleanup to implement the following rules. When I write "Ref" I mean (ref T), not anyref.
- an imported function cannot accept Ref parameters or return a Ref result
- an exported function cannot accept Ref parameters, but can return a Ref
result
- an imported global cannot have Ref type
- an exported global can have Ref type iff it is immutable
Together these rules ensure that struct types defined in a module do not "escape" that module via globals or functions in the sense that we need perform no type compatibility checks:
- at a call boundary in and out of a module
- when linking to an imported global
- when JS code stores into a global
In turn, that is desirable because we do not yet want to commit to any meaning for what it means for the manifest type of a value outside a module to be compatible with a type that is internal to the module.
(A similar conundrum for TypedObject properties of Ref type is solved slightly differently, see bug 1478982.)
Assignee | ||
Comment 1•7 years ago
|
||
Obviously these rules are fairly restrictive and a little user-hostile, and I am not at all averse to allowing more cases once we have struct.narrow or something like it to build on. However, this patch is part of the puzzle that will let me land the struct.whatever instructions in the first place without creating something that is unsound.
Attachment #8996341 -
Flags: review?(luke)
Assignee | ||
Comment 2•7 years ago
|
||
Attachment #8996341 -
Attachment is obsolete: true
Attachment #8996341 -
Flags: review?(luke)
Attachment #8996342 -
Flags: review?(luke)
Comment 3•7 years ago
|
||
I haven't looked at the patch, but there was something i wanted to mention: from this rule:
- an exported function cannot accept Ref parameters, but can return a Ref
result
It means that if a module exports a Table (which can implicitly export functions), then no functions can have ref parameters.
Assignee | ||
Comment 4•7 years ago
|
||
Oh, nice observation! I'll have to think about that. The alternative to the scheme I have here is to try to do what we do for int64, which is in a similar situation obviously; there we throw at the invocation point. That is hostile to static analysis / early checking but might solve the above problem.
![]() |
||
Comment 5•7 years ago
|
||
bbouvier++ I like the throw-on-invocation semantics, and we can have the exception text just say "Not Yet Implemented".
![]() |
||
Comment 6•7 years ago
|
||
Comment on attachment 8996342 [details] [diff] [review]
bug1479794-restrict-ref-types.patch
(I think that means this patch needs an update.)
Attachment #8996342 -
Flags: review?(luke)
Assignee | ||
Comment 7•7 years ago
|
||
Note/memo to self: There's the JS<->wasm boundary, but also the wasm<->wasm boundary when two modules are linked through exports/imports. In the latter case we also do not want to allow the link to succeed, this is stronger than the int64 restriction.
![]() |
||
Comment 8•7 years ago
|
||
No problem if it's necessary (and that may be a good argument for the static signature restriction instead of the dynamic one (which doesn't have a good cut point for wasm<->wasm) but I was wondering: why is it necessary to prevent wasm<->wasm?
Assignee | ||
Comment 9•7 years ago
|
||
(In reply to Luke Wagner [:luke] from comment #8)
> No problem if it's necessary (and that may be a good argument for the static
> signature restriction instead of the dynamic one (which doesn't have a good
> cut point for wasm<->wasm) but I was wondering: why is it necessary to
> prevent wasm<->wasm?
So this is cross-module wasm<->wasm, and the reason we should prevent those calls with Ref parameters or returns for the time being is that like JS<->wasm calls, they effectively export/import types. Until we have a notion of type compatibility - and we can't use nominal equivalence here - we can't check that type constraints are obeyed.
(anyref's fine, of course.)
Assignee | ||
Comment 10•7 years ago
|
||
Here's another attempt. See the commit message for details; in brief, we still have only static checks but that is sufficient because the restrictions are a little stronger than last time (notably including parameters and return types in all cases) and we also check the element initializers and call_indirect to handle the table cases. Extensive negative and positive test cases in ref-restrict.js, included here.
Again, the purpose of this patch is to clear the ground so that I can land my preliminary patches for struct.new, struct.get, struct.set and struct.narrow without risking any unsound behavior in the engine as a result of unsound or missing type compatibility checks where values flow into a module. Eventually these restrictions will be removed again.
Attachment #8996342 -
Attachment is obsolete: true
Attachment #9004495 -
Flags: review?(luke)
Attachment #9004495 -
Flags: feedback?(bbouvier)
![]() |
||
Comment 11•7 years ago
|
||
Comment on attachment 9004495 [details] [diff] [review]
bug1479794-restrict-ref-types-v2.patch
Review of attachment 9004495 [details] [diff] [review]:
-----------------------------------------------------------------
Makes sense; I like having the #ifdef so it's quite simple to chop this out later.
Attachment #9004495 -
Flags: review?(luke) → review+
Comment 12•7 years ago
|
||
Comment on attachment 9004495 [details] [diff] [review]
bug1479794-restrict-ref-types-v2.patch
Review of attachment 9004495 [details] [diff] [review]:
-----------------------------------------------------------------
The code looks good to me as is, but it's still possible to implicitly expose functions that are exposed for ref, right?
- have a wasm module declare a local table of size non-zero that's exported, with no declared segments
- the wasm module has a wasm function exposing ref, not exported either
- a JS caller instantiates the module and get the table
- Table.set(0, 0);
- Table.get(0)();
If so, I think you need to change the implementation of Table.set (WasmTableObject::setImpl) to check if the function designated by the function index exposes ref or not.
Attachment #9004495 -
Flags: feedback?(bbouvier) → feedback+
Comment 13•7 years ago
|
||
(oops, nevermind my comment, I remembered for some reason that Table.set() would take as the second argument indexes into the module's function index space, which is false)
Assignee | ||
Comment 14•7 years ago
|
||
But it does raise the issue of whether there are other back doors in the spirit of this. For example, we did have the situation where it's possible to export the table and thus revealing the functions, yet the functions in the table are not marked as exported; the patch prevents revealing functions exposed for Ref this way by checking the elemSegments, of course, but it is sneaky functionality.
Comment 15•7 years ago
|
||
Pushed by lhansen@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/9fcca8293f56
Do not expose Ref types outside the defining module. r=luke
Comment 16•7 years ago
|
||
bugherder |
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
status-firefox63:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla63
You need to log in
before you can comment on or make changes to this bug.
Description
•