examples(allocation): ensure message outlives host call (#1436)
Signed-off-by: Nuno Cruces <ncruces@users.noreply.github.com> Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com> Co-authored-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
This commit is contained in:
31
examples/allocation/tinygo/testdata/greet.go
vendored
31
examples/allocation/tinygo/testdata/greet.go
vendored
@@ -5,7 +5,7 @@ import "C"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"runtime"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ func greet(name string) {
|
|||||||
func log(message string) {
|
func log(message string) {
|
||||||
ptr, size := stringToPtr(message)
|
ptr, size := stringToPtr(message)
|
||||||
_log(ptr, size)
|
_log(ptr, size)
|
||||||
|
runtime.KeepAlive(message) // keep message alive until ptr is no longer needed.
|
||||||
}
|
}
|
||||||
|
|
||||||
// _log is a WebAssembly import which prints a string (linear memory offset,
|
// _log is a WebAssembly import which prints a string (linear memory offset,
|
||||||
@@ -30,7 +31,7 @@ func log(message string) {
|
|||||||
//
|
//
|
||||||
//go:wasm-module env
|
//go:wasm-module env
|
||||||
//export log
|
//export log
|
||||||
func _log(ptr uint32, size uint32)
|
func _log(ptr, size uint32)
|
||||||
|
|
||||||
// greeting gets a greeting for the name.
|
// greeting gets a greeting for the name.
|
||||||
func greeting(name string) string {
|
func greeting(name string) string {
|
||||||
@@ -63,32 +64,24 @@ func _greeting(ptr, size uint32) (ptrSize uint64) {
|
|||||||
// ptrToString returns a string from WebAssembly compatible numeric types
|
// ptrToString returns a string from WebAssembly compatible numeric types
|
||||||
// representing its pointer and length.
|
// representing its pointer and length.
|
||||||
func ptrToString(ptr uint32, size uint32) string {
|
func ptrToString(ptr uint32, size uint32) string {
|
||||||
// Get a slice view of the underlying bytes in the stream. We use SliceHeader, not StringHeader
|
return unsafe.String((*byte)(unsafe.Pointer(uintptr(ptr))), size)
|
||||||
// as it allows us to fix the capacity to what was allocated.
|
|
||||||
return *(*string)(unsafe.Pointer(&reflect.SliceHeader{
|
|
||||||
Data: uintptr(ptr),
|
|
||||||
Len: uintptr(size), // Tinygo requires these as uintptrs even if they are int fields.
|
|
||||||
Cap: uintptr(size), // ^^ See https://github.com/tinygo-org/tinygo/issues/1284
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// stringToPtr returns a pointer and size pair for the given string in a way
|
// stringToPtr returns a pointer and size pair for the given string in a way
|
||||||
// compatible with WebAssembly numeric types.
|
// compatible with WebAssembly numeric types.
|
||||||
|
// The returned pointer aliases the string hence the string must be kept alive
|
||||||
|
// until ptr is no longer needed.
|
||||||
func stringToPtr(s string) (uint32, uint32) {
|
func stringToPtr(s string) (uint32, uint32) {
|
||||||
buf := []byte(s)
|
ptr := unsafe.Pointer(unsafe.StringData(s))
|
||||||
ptr := &buf[0]
|
return uint32(uintptr(ptr)), uint32(len(s))
|
||||||
unsafePtr := uintptr(unsafe.Pointer(ptr))
|
|
||||||
return uint32(unsafePtr), uint32(len(buf))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// stringToLeakedPtr returns a pointer and size pair for the given string in a way
|
// stringToLeakedPtr returns a pointer and size pair for the given string in a way
|
||||||
// compatible with WebAssembly numeric types. The pointer is not automatically
|
// compatible with WebAssembly numeric types.
|
||||||
// managed by TinyGo hence it must be freed by the host.
|
// The pointer is not automatically managed by TinyGo hence it must be freed by the host.
|
||||||
func stringToLeakedPtr(s string) (uint32, uint32) {
|
func stringToLeakedPtr(s string) (uint32, uint32) {
|
||||||
size := C.ulong(len(s))
|
size := C.ulong(len(s))
|
||||||
ptr := unsafe.Pointer(C.malloc(size))
|
ptr := unsafe.Pointer(C.malloc(size))
|
||||||
|
copy(unsafe.Slice((*byte)(ptr), size), s)
|
||||||
copy(unsafe.Slice((*byte)(ptr), size), []byte(s))
|
return uint32(uintptr(ptr)), uint32(size)
|
||||||
|
|
||||||
return uint32(uintptr(ptr)), uint32(len(s))
|
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
examples/allocation/tinygo/testdata/greet.wasm
vendored
BIN
examples/allocation/tinygo/testdata/greet.wasm
vendored
Binary file not shown.
Reference in New Issue
Block a user