-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
cmd/compile: go:wasmimport allows pointers to pointers #59156
Comments
CC @golang/wasm |
cc @golang/compiler |
Is it only an issue for pointer to pointer? What about other (pointer to) data types (e.g. a struct), even if it doesn't contain pointers, how do we ensure the underlying data type at the other side (JS or other languages) has compatible memory layout? Maybe we permit only |
This is an issue for pointer-to-pointer, and also for pointers in inner fields of structs (see our second example).
There is no way to do this with the current WebAssembly tooling. ABIs are conventions that must be agreed upon by the WebAssembly hosts and guest modules. This is somewhat the root cause of this issue,
Allowing only scalar type is pretty close to what we are suggesting here I believe. We also expect the use of From the experience of developing #58141, bugs caused by mistakenly having pointers or I hope these answers are useful! |
Thanks. So it sounds like this is an issue for all data types (other than scalars). While the immediate issue is pointers, I think we also don't have guarantees to ensure other data types are laid out exactly same (e.g. even for a struct with all scalar fields, do they have the same padding rules? Maybe they do, but I'm not sure we want to guarantee that). So, I would think we allow only scalar types that directly correspond to a Wasm type, |
Yes 👍
Generally the alignment rules seem to work well enough that we haven't had issues with these, the rules used by Go appear to match what is expected by WASI-compatible runtimes, tho it's possible that this is only accidental and may be architecture dependent? Starting with the 4 scalar types + @johanbrandhorst @evanphx What do you think? |
TL,DR: We should instead prioritize switching to 32bit pointers so that Go works the same as other Webassembly compilers. Hi all, The UX of only allowing that set of types will make public usage of wasmimport really awkward. If this was only for our usage within runtime/syscall, it would probably be fine. But forcing every integration to hand write a set of wrappers (which are pretty hard to write) is not going to serve us very well. It would be the equiv of cgo only allowing those types and not containing of the automapping code. Given this, I think we should go the other direction entirely, which is to prioritize switch to 32bit pointers so that this issue goes away entirely. The only other issue would be alignment, which @achille-roussel has indicated hasn't been an issue, mostly because Go's alignment is mostly the same as LLVM/etc. This, I'll say, is probably the worst specified part of Webassembly. There is mostly a handshake agreement on ABI currently, but we can't ignore that because doing see means that compiling Go to Webassembly means our users can't use that Go code with existing Webassembly infrastructure (which is the whole point of doing this). |
Just noting here that we intend to submit a proposal detailing the move to 32 bit, we're not trying to make this issue discussion the forum for that discussion 😅. |
Thanks.
The
For cgo, on the Go side it usually uses explicit C types like Maybe we want to introduce a
I don't think the issue really goes away entirely. Maybe it doesn't cause any immediate problem now. But I don't think we want to guarantee in the language spec that Go's struct layout etc. has to match Wasm's. One possibility is that we document that the user of wasmimport is responsible for making sure the layout agrees on both sides. (But it might still change from time to time?)
Thanks. (Not sure this is the best place to discuss) A few questions:
|
Thanks for your comments. I think we'd prefer to fix this bug with your suggested reduced set of allowed types in the parameters. That is, only allow the parameters of a function using
We'll prepare to submit a CL with this change shortly. Re: 32 bit port, I think our current thinking is a new port, EDIT: removed 8 and 16 bit integer types for now. |
Change https://go.dev/cl/483415 mentions this issue: |
Background
The
go:wasmimport
directive was added in #38248 and has since been used to implement the prototype implementation of the WASI port. It is currently limited to use in theruntime
,syscall
andsyscall/js
standard library packages. With #59149 we want to allow any Go user to write their owngo:wasmimport
statements to access functions implemented on the WASI host.Wasm today uses 32 bit pointers, while internally in the Go Wasm implementation we use 64 bit pointers. When a function is decorated with the
go:wasmimport
directive, the compiler translates the arguments (including pointers) to Wasm types. However, pointers to structs containing pointers cannot have their pointer fields converted in the same way since the conversion would require copying the objects to new memory locations, including the conversion of pointer fields to 32 bits, and copying the data back into the objects when the call returns. The mechanism would have to recursively walk the objects, dealing with pointer cycles, and likely introduce a significant overhead when callinggo:wasmimport
functions.What is the behaviour today?
The compiler does not error when compiling functions with arguments that point to pointers. At runtime, there is an ABI mismatch between the Go program and the Wasm host modules, the latter expecting pointers to be 32 bits, causing misalignment of fields in struct types passed by pointer to
go:wasmimport
functions.What did I expect to see?
I expected the compiler to disallow functions using arguments that point to pointers so we prevent users of
go:wasmimport
from constructing programs with a memory layout that is incompatible with the Wasm host.Discussion
The following should be allowed (no internal struct pointers):
The following should not be allowed (types contain pointers to pointers):
The text was updated successfully, but these errors were encountered: