memory: avoid integer overflow (#1459)
Signed-off-by: Nuno Cruces <ncruces@users.noreply.github.com>
This commit is contained in:
@@ -111,7 +111,7 @@ func (m *MemoryInstance) ReadFloat64Le(offset uint32) (float64, bool) {
|
||||
|
||||
// Read implements the same method as documented on api.Memory.
|
||||
func (m *MemoryInstance) Read(offset, byteCount uint32) ([]byte, bool) {
|
||||
if !m.hasSize(offset, byteCount) {
|
||||
if !m.hasSize(offset, uint64(byteCount)) {
|
||||
return nil, false
|
||||
}
|
||||
return m.Buffer[offset : offset+byteCount : offset+byteCount], true
|
||||
@@ -157,7 +157,7 @@ func (m *MemoryInstance) WriteFloat64Le(offset uint32, v float64) bool {
|
||||
|
||||
// Write implements the same method as documented on api.Memory.
|
||||
func (m *MemoryInstance) Write(offset uint32, val []byte) bool {
|
||||
if !m.hasSize(offset, uint32(len(val))) {
|
||||
if !m.hasSize(offset, uint64(len(val))) {
|
||||
return false
|
||||
}
|
||||
copy(m.Buffer[offset:], val)
|
||||
@@ -166,7 +166,7 @@ func (m *MemoryInstance) Write(offset uint32, val []byte) bool {
|
||||
|
||||
// WriteString implements the same method as documented on api.Memory.
|
||||
func (m *MemoryInstance) WriteString(offset uint32, val string) bool {
|
||||
if !m.hasSize(offset, uint32(len(val))) {
|
||||
if !m.hasSize(offset, uint64(len(val))) {
|
||||
return false
|
||||
}
|
||||
copy(m.Buffer[offset:], val)
|
||||
@@ -243,8 +243,8 @@ func (m *MemoryInstance) size() uint32 {
|
||||
// hasSize returns true if Len is sufficient for byteCount at the given offset.
|
||||
//
|
||||
// Note: This is always fine, because memory can grow, but never shrink.
|
||||
func (m *MemoryInstance) hasSize(offset uint32, byteCount uint32) bool {
|
||||
return uint64(offset)+uint64(byteCount) <= uint64(len(m.Buffer)) // uint64 prevents overflow on add
|
||||
func (m *MemoryInstance) hasSize(offset uint32, byteCount uint64) bool {
|
||||
return uint64(offset)+byteCount <= uint64(len(m.Buffer)) // uint64 prevents overflow on add
|
||||
}
|
||||
|
||||
// readUint32Le implements ReadUint32Le without using a context. This is extracted as both ints and floats are stored in
|
||||
|
||||
@@ -2,8 +2,10 @@ package wasm
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
@@ -194,7 +196,7 @@ func TestMemoryInstance_HasSize(t *testing.T) {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require.Equal(t, tc.expected, memory.hasSize(tc.offset, uint32(tc.sizeInBytes)))
|
||||
require.Equal(t, tc.expected, memory.hasSize(tc.offset, tc.sizeInBytes))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -735,6 +737,23 @@ func TestMemoryInstance_Write(t *testing.T) {
|
||||
require.False(t, ok)
|
||||
}
|
||||
|
||||
func TestMemoryInstance_Write_overflow(t *testing.T) {
|
||||
mem := &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1}
|
||||
|
||||
// Test overflow
|
||||
huge := uint64(math.MaxUint32 + 1 + 4)
|
||||
if huge != uint64(int(huge)) {
|
||||
t.Skip("Skipping on 32-bit")
|
||||
}
|
||||
|
||||
buf := []byte{16, 0, 0, 4}
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
header.Len = int(huge)
|
||||
header.Cap = int(huge)
|
||||
|
||||
require.False(t, mem.Write(4, buf))
|
||||
}
|
||||
|
||||
func TestMemoryInstance_WriteString(t *testing.T) {
|
||||
mem := &MemoryInstance{Buffer: []byte{0, 0, 0, 0, 16, 0, 0, 0}, Min: 1}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user