mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-08 13:03:39 +00:00
wasm,wasi: make sure buffers returned by malloc are not freed until f… (#3148)
* wasm,wasi: make sure buffers returned by malloc are not freed until free is called
This commit is contained in:
@@ -61,31 +61,54 @@ func growHeap() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// The below functions override the default allocator of wasi-libc.
|
||||
// Most functions are defined but unimplemented to make sure that if there is
|
||||
// any code using them, they will get an error instead of (incorrectly) using
|
||||
// the wasi-libc dlmalloc heap implementation instead. If they are needed by any
|
||||
// program, they can certainly be implemented.
|
||||
// The below functions override the default allocator of wasi-libc. This ensures
|
||||
// code linked from other languages can allocate memory without colliding with
|
||||
// our GC allocations.
|
||||
|
||||
var allocs = make(map[uintptr][]byte)
|
||||
|
||||
//export malloc
|
||||
func libc_malloc(size uintptr) unsafe.Pointer {
|
||||
return alloc(size, nil)
|
||||
buf := make([]byte, size)
|
||||
ptr := unsafe.Pointer(&buf[0])
|
||||
allocs[uintptr(ptr)] = buf
|
||||
return ptr
|
||||
}
|
||||
|
||||
//export free
|
||||
func libc_free(ptr unsafe.Pointer) {
|
||||
free(ptr)
|
||||
if ptr == nil {
|
||||
return
|
||||
}
|
||||
if _, ok := allocs[uintptr(ptr)]; ok {
|
||||
delete(allocs, uintptr(ptr))
|
||||
} else {
|
||||
panic("free: invalid pointer")
|
||||
}
|
||||
}
|
||||
|
||||
//export calloc
|
||||
func libc_calloc(nmemb, size uintptr) unsafe.Pointer {
|
||||
// Note: we could be even more correct here and check that nmemb * size
|
||||
// doesn't overflow. However the current implementation should normally work
|
||||
// fine.
|
||||
return alloc(nmemb*size, nil)
|
||||
// No difference between calloc and malloc.
|
||||
return libc_malloc(nmemb * size)
|
||||
}
|
||||
|
||||
//export realloc
|
||||
func libc_realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer {
|
||||
return realloc(ptr, size)
|
||||
func libc_realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer {
|
||||
// It's hard to optimize this to expand the current buffer with our GC, but
|
||||
// it is theoretically possible. For now, just always allocate fresh.
|
||||
buf := make([]byte, size)
|
||||
|
||||
if oldPtr != nil {
|
||||
if oldBuf, ok := allocs[uintptr(oldPtr)]; ok {
|
||||
copy(buf, oldBuf)
|
||||
delete(allocs, uintptr(oldPtr))
|
||||
} else {
|
||||
panic("realloc: invalid pointer")
|
||||
}
|
||||
}
|
||||
|
||||
ptr := unsafe.Pointer(&buf[0])
|
||||
allocs[uintptr(ptr)] = buf
|
||||
return ptr
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user