Skip to content

Commit 53c0158

Browse files
achille-rousseljohanbrandhorst
authored andcommitted
wasm: restrict supported types in go:wasmimport function signatures
Changes the set of types supported in functions declared with the go:wasmimport directive to only allow 32 bits and 64 bits integers and floats, as well as unsafe.Pointer in parameters only. Both the compiler code and the standard library are updated because the new restrictions require modifying the use of go:wasmimport in the syscall and runtime packages. In preparation of enabling packages outside of the standard library to use the go:wasmimport directive, the error messages are modified to carry more context and use ErrorfAt instead of Fatalf to avoid printing the compiler stack trace when a function with an invalid signature is encountered. Fixes #59156 Change-Id: Ied8317f8ead9c28f0297060ac35a5b5255ab49db Reviewed-on: https://go-review.googlesource.com/c/go/+/483415 Reviewed-by: Cherry Mui <[email protected]> Reviewed-by: Johan Brandhorst-Satzkorn <[email protected]> Reviewed-by: David Chase <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Johan Brandhorst-Satzkorn <[email protected]>
1 parent 92a3cb9 commit 53c0158

File tree

4 files changed

+106
-73
lines changed

4 files changed

+106
-73
lines changed

src/cmd/compile/internal/ssagen/abi.go

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -366,23 +366,48 @@ func CreateWasmImportWrapper(fn *ir.Func) bool {
366366
return true
367367
}
368368

369-
func toWasmFields(result *abi.ABIParamResultInfo, abiParams []abi.ABIParamAssignment) []obj.WasmField {
369+
func paramsToWasmFields(f *ir.Func, result *abi.ABIParamResultInfo, abiParams []abi.ABIParamAssignment) []obj.WasmField {
370370
wfs := make([]obj.WasmField, len(abiParams))
371371
for i, p := range abiParams {
372372
t := p.Type
373-
switch {
374-
case t.IsInteger() && t.Size() == 4:
373+
switch t.Kind() {
374+
case types.TINT32, types.TUINT32:
375375
wfs[i].Type = obj.WasmI32
376-
case t.IsInteger() && t.Size() == 8:
376+
case types.TINT64, types.TUINT64:
377377
wfs[i].Type = obj.WasmI64
378-
case t.IsFloat() && t.Size() == 4:
378+
case types.TFLOAT32:
379379
wfs[i].Type = obj.WasmF32
380-
case t.IsFloat() && t.Size() == 8:
380+
case types.TFLOAT64:
381381
wfs[i].Type = obj.WasmF64
382-
case t.IsPtr():
382+
case types.TUNSAFEPTR:
383383
wfs[i].Type = obj.WasmPtr
384384
default:
385-
base.Fatalf("wasm import has bad function signature")
385+
base.ErrorfAt(f.Pos(), 0, "go:wasmimport %s %s: unsupported parameter type %s", f.WasmImport.Module, f.WasmImport.Name, t.String())
386+
}
387+
wfs[i].Offset = p.FrameOffset(result)
388+
}
389+
return wfs
390+
}
391+
392+
func resultsToWasmFields(f *ir.Func, result *abi.ABIParamResultInfo, abiParams []abi.ABIParamAssignment) []obj.WasmField {
393+
if len(abiParams) > 1 {
394+
base.ErrorfAt(f.Pos(), 0, "go:wasmimport %s %s: too many return values", f.WasmImport.Module, f.WasmImport.Name)
395+
return nil
396+
}
397+
wfs := make([]obj.WasmField, len(abiParams))
398+
for i, p := range abiParams {
399+
t := p.Type
400+
switch t.Kind() {
401+
case types.TINT32, types.TUINT32:
402+
wfs[i].Type = obj.WasmI32
403+
case types.TINT64, types.TUINT64:
404+
wfs[i].Type = obj.WasmI64
405+
case types.TFLOAT32:
406+
wfs[i].Type = obj.WasmF32
407+
case types.TFLOAT64:
408+
wfs[i].Type = obj.WasmF64
409+
default:
410+
base.ErrorfAt(f.Pos(), 0, "go:wasmimport %s %s: unsupported result type %s", f.WasmImport.Module, f.WasmImport.Name, t.String())
386411
}
387412
wfs[i].Offset = p.FrameOffset(result)
388413
}
@@ -419,8 +444,8 @@ func setupWasmABI(f *ir.Func) {
419444
// (import "a_module" "add" (func (param i32 i32) (result i32)))
420445
abiConfig := AbiForBodylessFuncStackMap(f)
421446
abiInfo := abiConfig.ABIAnalyzeFuncType(f.Type().FuncType())
422-
wi.Params = toWasmFields(abiInfo, abiInfo.InParams())
423-
wi.Results = toWasmFields(abiInfo, abiInfo.OutParams())
447+
wi.Params = paramsToWasmFields(f, abiInfo, abiInfo.InParams())
448+
wi.Results = resultsToWasmFields(f, abiInfo, abiInfo.OutParams())
424449
}
425450
f.LSym.Func().WasmImport = &wi
426451
}

src/runtime/os_wasip1.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,31 +48,31 @@ func exit(code int32)
4848

4949
//go:wasmimport wasi_snapshot_preview1 args_get
5050
//go:noescape
51-
func args_get(argv *uintptr32, argvBuf *byte) errno
51+
func args_get(argv, argvBuf unsafe.Pointer) errno
5252

5353
//go:wasmimport wasi_snapshot_preview1 args_sizes_get
5454
//go:noescape
55-
func args_sizes_get(argc *size, argvBufLen *size) errno
55+
func args_sizes_get(argc, argvBufLen unsafe.Pointer) errno
5656

5757
//go:wasmimport wasi_snapshot_preview1 clock_time_get
5858
//go:noescape
59-
func clock_time_get(clock_id clockid, precision timestamp, time *timestamp) errno
59+
func clock_time_get(clock_id clockid, precision timestamp, time unsafe.Pointer) errno
6060

6161
//go:wasmimport wasi_snapshot_preview1 environ_get
6262
//go:noescape
63-
func environ_get(environ *uintptr32, environBuf *byte) errno
63+
func environ_get(environ, environBuf unsafe.Pointer) errno
6464

6565
//go:wasmimport wasi_snapshot_preview1 environ_sizes_get
6666
//go:noescape
67-
func environ_sizes_get(environCount *size, environBufLen *size) errno
67+
func environ_sizes_get(environCount, environBufLen unsafe.Pointer) errno
6868

6969
//go:wasmimport wasi_snapshot_preview1 fd_write
7070
//go:noescape
71-
func fd_write(fd int32, iovs *iovec, iovsLen size, nwritten *size) errno
71+
func fd_write(fd int32, iovs unsafe.Pointer, iovsLen size, nwritten unsafe.Pointer) errno
7272

7373
//go:wasmimport wasi_snapshot_preview1 random_get
7474
//go:noescape
75-
func random_get(buf *byte, bufLen size) errno
75+
func random_get(buf unsafe.Pointer, bufLen size) errno
7676

7777
type eventtype = uint8
7878

@@ -140,15 +140,15 @@ func (u *subscriptionUnion) subscriptionClock() *subscriptionClock {
140140

141141
//go:wasmimport wasi_snapshot_preview1 poll_oneoff
142142
//go:noescape
143-
func poll_oneoff(in *subscription, out *event, nsubscriptions size, nevents *size) errno
143+
func poll_oneoff(in, out unsafe.Pointer, nsubscriptions size, nevents unsafe.Pointer) errno
144144

145145
func write1(fd uintptr, p unsafe.Pointer, n int32) int32 {
146146
iov := iovec{
147147
buf: uintptr32(uintptr(p)),
148148
bufLen: size(n),
149149
}
150150
var nwritten size
151-
if fd_write(int32(fd), &iov, 1, &nwritten) != 0 {
151+
if fd_write(int32(fd), unsafe.Pointer(&iov), 1, unsafe.Pointer(&nwritten)) != 0 {
152152
throw("fd_write failed")
153153
}
154154
return int32(nwritten)
@@ -167,13 +167,13 @@ func usleep(usec uint32) {
167167
subscription.timeout = timestamp(usec) * 1e3
168168
subscription.precision = 1e3
169169

170-
if poll_oneoff(&in, &out, 1, &nevents) != 0 {
170+
if poll_oneoff(unsafe.Pointer(&in), unsafe.Pointer(&out), 1, unsafe.Pointer(&nevents)) != 0 {
171171
throw("wasi_snapshot_preview1.poll_oneoff")
172172
}
173173
}
174174

175175
func getRandomData(r []byte) {
176-
if random_get(&r[0], size(len(r))) != 0 {
176+
if random_get(unsafe.Pointer(&r[0]), size(len(r))) != 0 {
177177
throw("random_get failed")
178178
}
179179
}
@@ -182,15 +182,15 @@ func goenvs() {
182182
// arguments
183183
var argc size
184184
var argvBufLen size
185-
if args_sizes_get(&argc, &argvBufLen) != 0 {
185+
if args_sizes_get(unsafe.Pointer(&argc), unsafe.Pointer(&argvBufLen)) != 0 {
186186
throw("args_sizes_get failed")
187187
}
188188

189189
argslice = make([]string, argc)
190190
if argc > 0 {
191191
argv := make([]uintptr32, argc)
192192
argvBuf := make([]byte, argvBufLen)
193-
if args_get(&argv[0], &argvBuf[0]) != 0 {
193+
if args_get(unsafe.Pointer(&argv[0]), unsafe.Pointer(&argvBuf[0])) != 0 {
194194
throw("args_get failed")
195195
}
196196

@@ -207,15 +207,15 @@ func goenvs() {
207207
// environment
208208
var environCount size
209209
var environBufLen size
210-
if environ_sizes_get(&environCount, &environBufLen) != 0 {
210+
if environ_sizes_get(unsafe.Pointer(&environCount), unsafe.Pointer(&environBufLen)) != 0 {
211211
throw("environ_sizes_get failed")
212212
}
213213

214214
envs = make([]string, environCount)
215215
if environCount > 0 {
216216
environ := make([]uintptr32, environCount)
217217
environBuf := make([]byte, environBufLen)
218-
if environ_get(&environ[0], &environBuf[0]) != 0 {
218+
if environ_get(unsafe.Pointer(&environ[0]), unsafe.Pointer(&environBuf[0])) != 0 {
219219
throw("environ_get failed")
220220
}
221221

@@ -236,15 +236,15 @@ func walltime() (sec int64, nsec int32) {
236236

237237
func walltime1() (sec int64, nsec int32) {
238238
var time timestamp
239-
if clock_time_get(clockRealtime, 0, &time) != 0 {
239+
if clock_time_get(clockRealtime, 0, unsafe.Pointer(&time)) != 0 {
240240
throw("clock_time_get failed")
241241
}
242242
return int64(time / 1000000000), int32(time % 1000000000)
243243
}
244244

245245
func nanotime1() int64 {
246246
var time timestamp
247-
if clock_time_get(clockMonotonic, 0, &time) != 0 {
247+
if clock_time_get(clockMonotonic, 0, unsafe.Pointer(&time)) != 0 {
248248
throw("clock_time_get failed")
249249
}
250250
return int64(time)

0 commit comments

Comments
 (0)