mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-25 03:47:18 +00:00
vm: fix PACKMAP operation
Close #3613 Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
This commit is contained in:
parent
176593b31f
commit
9082c6ea1a
4 changed files with 49 additions and 8 deletions
|
@ -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{
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
13
pkg/vm/vm.go
13
pkg/vm/vm.go
|
@ -1214,15 +1214,16 @@ 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 {
|
||||
m := 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
|
||||
if key.Item() == nil {
|
||||
panic("no key found")
|
||||
}
|
||||
m.Add(key.value, val)
|
||||
}
|
||||
v.estack.PushItem(stackitem.NewMapWithValue(items))
|
||||
v.estack.PushItem(m)
|
||||
|
||||
case opcode.PACKSTRUCT, opcode.PACK:
|
||||
n := toInt(v.estack.Pop().BigInt())
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Reference in a new issue