Skip to content

Commit

Permalink
vm: fix packmap operation
Browse files Browse the repository at this point in the history
Close #3613

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
  • Loading branch information
AliceInHunterland committed Nov 14, 2024
1 parent c2b4d32 commit 709e948
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 26 deletions.
7 changes: 0 additions & 7 deletions pkg/rpcclient/nep11/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,6 @@ func TestUnwrapKnownProperties(t *testing.T) {
require.NotNil(t, m)
require.Equal(t, 0, len(m))

m, err = UnwrapKnownProperties(stackitem.NewMapWithValue([]stackitem.MapElement{
{Key: stackitem.Make([]stackitem.Item{}), Value: stackitem.Make("thing")},
}), nil)
require.NoError(t, err)
require.NotNil(t, m)
require.Equal(t, 0, len(m))

_, err = UnwrapKnownProperties(stackitem.NewMapWithValue([]stackitem.MapElement{
{Key: stackitem.Make("name"), Value: stackitem.Make([]stackitem.Item{})},
}), nil)
Expand Down
10 changes: 7 additions & 3 deletions pkg/vm/stackitem/item.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,12 +826,16 @@ func NewMap() *Map {

// NewMapWithValue returns a new Map object filled with the specified value.
func NewMapWithValue(value []MapElement) *Map {
res := NewMap()
if value != nil {
return &Map{
value: value,
for i := range value {
if err := IsValidMapKey(value[i].Key); err != nil {
panic(err)

Check warning on line 833 in pkg/vm/stackitem/item.go

View check run for this annotation

Codecov / codecov/patch

pkg/vm/stackitem/item.go#L833

Added line #L833 was not covered by tests
}
res.Add(value[i].Key, value[i].Value)
}
}
return NewMap()
return res
}

// Value implements the Item interface.
Expand Down
21 changes: 12 additions & 9 deletions pkg/vm/stackitem/item_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,14 +591,17 @@ func TestDeepCopy(t *testing.T) {
})

t.Run("Map", func(t *testing.T) {
m := NewMapWithValue(make([]MapElement, 2))
m.value[0] = MapElement{Key: NewBool(true), Value: m}
m.value[1] = MapElement{Key: NewBigInteger(big.NewInt(1)), Value: NewByteArray([]byte{1, 2, 3})}

actual := DeepCopy(m, false)
m.isReadOnly = true // tiny hack for test to be able to compare object references.
require.Equal(t, m, actual)
require.False(t, m == actual)
require.True(t, actual == actual.(*Map).value[0].Value)
m := make([]MapElement, 2)
testVal := NewMap()
testVal.Add(NewBool(false), NewBool(false))
testVal.MarkAsReadOnly()
m[0] = MapElement{Key: NewBool(true), Value: testVal}
m[1] = MapElement{Key: NewBigInteger(big.NewInt(1)), Value: NewByteArray([]byte{1, 2, 3})}
res := NewMapWithValue(m)
res.MarkAsReadOnly()
actual := DeepCopy(res, false)
require.Equal(t, res, actual)
require.False(t, res == actual)
require.Equal(t, testVal, actual.(*Map).value[0].Value)
})
}
4 changes: 3 additions & 1 deletion pkg/vm/stackitem/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,10 @@ func TestToJSONWithTypesBadCases(t *testing.T) {
t.Run("overflow on map key", func(t *testing.T) {
m := NewMapWithValue([]MapElement{
{NewBool(true), NewBool(true)},
{NewByteArray(bigBuf), NewBool(true)},
})
for i := 1; i < MaxSize/85; i++ {
m.Add(NewBigInteger(big.NewInt(int64(i))), NewBigInteger(big.NewInt(123456)))
}
_, err := ToJSONWithTypes(m)
require.ErrorIs(t, err, errTooBigSize)
})
Expand Down
2 changes: 1 addition & 1 deletion pkg/vm/stackitem/serialization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func TestSerializeLimited(t *testing.T) {
bigMap := make([]MapElement, customLimit/2)
for i := range bigMap {
bigMap[i] = MapElement{
Key: NewByteArray([]byte("key")),
Key: NewByteArray([]byte("key" + strconv.Itoa(i))),
Value: NewBool(true),
}
}
Expand Down
9 changes: 4 additions & 5 deletions pkg/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1214,15 +1214,14 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
panic("invalid length")
}

items := make([]stackitem.MapElement, n)
for i := range n {
newMap := stackitem.NewMap()
for range n {
key := v.estack.Pop()
validateMapKey(key)
val := v.estack.Pop().value
items[i].Key = key.value
items[i].Value = val
newMap.Add(key.Item(), val)
}
v.estack.PushItem(stackitem.NewMapWithValue(items))
v.estack.PushItem(newMap)

case opcode.PACKSTRUCT, opcode.PACK:
n := toInt(v.estack.Pop().BigInt())
Expand Down

0 comments on commit 709e948

Please sign in to comment.