Skip to content

Commit

Permalink
add set tests
Browse files Browse the repository at this point in the history
  • Loading branch information
facuMH committed Sep 12, 2024
1 parent 8dfb5a1 commit d57c1ce
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 13 deletions.
8 changes: 4 additions & 4 deletions go/interpreter/lfvm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ func opCallDataCopy(c *context) {
return
}

if err := c.memory.Set(memOffset64, length64, getData(c.params.Input, dataOffset64, length64)); err != nil {
if err := c.memory.set(memOffset64, length64, getData(c.params.Input, dataOffset64, length64)); err != nil {
c.signalError()
}
}
Expand Down Expand Up @@ -805,7 +805,7 @@ func opCodeCopy(c *context) {
return
}
codeCopy := getData(c.params.Code, uint64CodeOffset, length.Uint64())
if err := c.memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy); err != nil {
if err := c.memory.set(memOffset.Uint64(), length.Uint64(), codeCopy); err != nil {
c.signalError()
}
}
Expand Down Expand Up @@ -1056,7 +1056,7 @@ func opExtCodeCopy(c *context) {
return
}
codeCopy := getData(c.context.GetCode(addr), uint64CodeOffset, length.Uint64())
if err = c.memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy); err != nil {
if err = c.memory.set(memOffset.Uint64(), length.Uint64(), codeCopy); err != nil {
c.signalError()
}
}
Expand Down Expand Up @@ -1218,7 +1218,7 @@ func genericCall(c *context, kind tosca.CallKind) {
ret, err := c.context.Call(kind, callParams)

if err == nil {
if memSetErr := c.memory.Set(retOffset.Uint64(), retSize.Uint64(), ret.Output); memSetErr != nil {
if memSetErr := c.memory.set(retOffset.Uint64(), retSize.Uint64(), ret.Output); memSetErr != nil {
c.signalError()
}
}
Expand Down
20 changes: 12 additions & 8 deletions go/interpreter/lfvm/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func (m *Memory) Len() uint64 {
}

// setByte sets a byte at the given offset, expanding memory as needed and charging for it.
// If any error occurs during EnsureCapacity, this is reflected in context status.
// Returns error if insufficient memory or offset+1 overflows.
func (m *Memory) setByte(offset uint64, value byte, c *context) error {
return m.setWithCapacityAndGasCheck(offset, 1, []byte{value}, c)
}
Expand Down Expand Up @@ -163,29 +163,33 @@ func (m *Memory) SetWord(offset uint64, value *uint256.Int, c *context) error {
return nil
}

func (m *Memory) Set(offset, size uint64, value []byte) error {
// set sets the given value at the given offset.
// Returns error if insufficient memory or offset+size overflows.
func (m *Memory) set(offset, size uint64, value []byte) error {
if size > 0 {
if offset+size < offset {
return errGasUintOverflow
}
if offset+size > m.Len() {
return fmt.Errorf("memory too small, size %d, attempted to write %d bytes at %d", m.Len(), size, offset)
return makeInsufficientMemoryError(m.Len(), size, offset)
}
copy(m.store[offset:offset+size], value)
}
return nil
}

func makeInsufficientMemoryError(memSize, size, offset uint64) error {
return tosca.ConstError(fmt.Sprintf("memory too small, size %d, attempted to write %d bytes at %d", memSize, size, offset))
}

// setWithCapacityAndGasCheck sets the given value at the given offset, expands memory as needed and charges for it.
// Returns error if insufficient memory or offset+size overflows.
func (m *Memory) setWithCapacityAndGasCheck(offset, size uint64, value []byte, c *context) error {
err := m.EnsureCapacity(offset, size, c)
if err != nil {
return err
}
err = m.Set(offset, size, value)
if err != nil {
return err
}
return nil
return m.set(offset, size, value)
}

func (m *Memory) SetWithCapacityCheck(offset, size uint64, value []byte) error {
Expand Down
76 changes: 75 additions & 1 deletion go/interpreter/lfvm/memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package lfvm

import (
"bytes"
"errors"
"math"
"testing"
Expand Down Expand Up @@ -87,7 +88,9 @@ func TestMemory_SetByte_SuccessfulCases(t *testing.T) {
if err != nil {
t.Errorf("unexpected error, want: %v, got: %v", nil, err)
}
if m.Len() < test.offset {
// if memory expansion is needed, it expands up to offset+1
// if no expansion is needed, is because memory is already large enough
if m.Len() <= test.offset {
t.Errorf("unexpected memory size, want: %d, got: %d", test.offset, m.Len())
}
if m.store[test.offset] != value {
Expand Down Expand Up @@ -130,3 +133,74 @@ func TestMemory_SetByte_ErrorCases(t *testing.T) {
})
}
}

func TestMemory_Set_SuccessfulCases(t *testing.T) {

memoryOriginalSize := uint64(8)
offset := uint64(1)
// data of size (memoryOriginalSize - offset), to ensure it would fit in memory
data := make([]byte, memoryOriginalSize-offset)
for i := range data {
// add non zero values.
data[i] = byte(i + 1)
}
size := uint64(len(data))

m := NewMemory()
m.store = make([]byte, memoryOriginalSize)

err := m.set(offset, size, data)
if err != nil {
t.Fatalf("unexpected error, want: %v, got: %v", nil, err)
}

if m.Len() != memoryOriginalSize {
t.Errorf("set should not change memory size, want: %d, got: %d", memoryOriginalSize, m.Len())
}
if want := append([]byte{0x0}, data...); !bytes.Equal(m.store, want) {
t.Errorf("unexpected memory value, want: %x, got: %x", want, m.store)
}

}

func TestMemory_Set_ErrorCases(t *testing.T) {

tests := map[string]struct {
size uint64
offset uint64
expected error
}{
"size overflow": {
size: math.MaxUint64,
offset: 1,
expected: errGasUintOverflow,
},
"offset overflow": {
size: 32,
offset: math.MaxUint64,
expected: errGasUintOverflow,
},
"not enough memory": {
size: 32,
offset: 32,
expected: makeInsufficientMemoryError(8, 32, 32),
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {

m := NewMemory()
m.store = make([]byte, 8)

// since we are only testing for failed cases, data is not relevant because
// the internal checks are done with offset and size parameters.
err := m.set(test.offset, test.size, []byte{})

if !errors.Is(err, test.expected) {
t.Errorf("unexpected error, want: %v, got: %v", test.expected, err)
}

})
}
}

0 comments on commit d57c1ce

Please sign in to comment.