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 <[email protected]>
  • Loading branch information
AliceInHunterland committed Nov 18, 2024
1 parent 990634a commit ea76b26
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 9 deletions.
3 changes: 2 additions & 1 deletion pkg/vm/stackitem/item.go
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,8 @@ func NewMap() *Map {
}
}

// NewMapWithValue returns a new Map object filled with the specified value.
// NewMapWithValue returns a new Map object filled with the specified value
// without value validation.
func NewMapWithValue(value []MapElement) *Map {
if value != nil {
return &Map{
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
14 changes: 7 additions & 7 deletions pkg/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1214,15 +1214,15 @@ 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 {
key := v.estack.Pop()
validateMapKey(key)
m := stackitem.NewMap()
for range n {
key := v.estack.Pop().value
val := v.estack.Pop().value
items[i].Key = key.value
items[i].Value = val
if key != nil {
m.Add(key, val)
}
}
v.estack.PushItem(stackitem.NewMapWithValue(items))
v.estack.PushItem(m)

case opcode.PACKSTRUCT, opcode.PACK:
n := toInt(v.estack.Pop().BigInt())
Expand Down
39 changes: 39 additions & 0 deletions pkg/vm/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2083,6 +2083,45 @@ func TestUNPACKBadNotArray(t *testing.T) {
runWithArgs(t, prog, nil, 1)
}

func TestPACKMAPDuplicateKeys(t *testing.T) {
prog := makeProgram(opcode.PACKMAP)
vm := load(prog)

keys := []string{"duplicateKey", "uniqueKey", "duplicateKey", "anotherUniqueKey"}
values := []string{"value1", "value2", "value3", "value4"}

for i := range keys {
vm.estack.PushVal(values[i])
vm.estack.PushVal(keys[i])
}

vm.estack.PushVal(len(keys))
runVM(t, vm)

require.Equal(t, 1, vm.estack.Len())
packedItem := vm.estack.Pop().Item()
require.Equal(t, stackitem.MapT, packedItem.Type())

packedMap := packedItem.(*stackitem.Map)
require.Equal(t, 3, packedMap.Len())

expected := []stackitem.MapElement{
{
Key: stackitem.NewByteArray([]byte("anotherUniqueKey")),
Value: stackitem.NewByteArray([]byte("value4")),
},
{
Key: stackitem.NewByteArray([]byte("duplicateKey")),
Value: stackitem.NewByteArray([]byte("value1")),
},
{
Key: stackitem.NewByteArray([]byte("uniqueKey")),
Value: stackitem.NewByteArray([]byte("value2")),
},
}
require.Equal(t, expected, packedMap.Value())
}

func TestUNPACKGood(t *testing.T) {
prog := makeProgram(opcode.UNPACK)
elements := []int{55, 34, 42}
Expand Down

0 comments on commit ea76b26

Please sign in to comment.