mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-26 19:42:23 +00:00
vm: fail if NEWSTRUCT/NEWARRAY argument is not an integer
NEO3 VM does not support creating new Array from a Struct. For this purpose CONVERT opcode is used.
This commit is contained in:
parent
1a0290edc6
commit
063c29636b
2 changed files with 28 additions and 55 deletions
46
pkg/vm/vm.go
46
pkg/vm/vm.go
|
@ -981,46 +981,28 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
|
||||
case opcode.NEWARRAY, opcode.NEWARRAYT:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *StructItem:
|
||||
arr := make([]StackItem, len(t.value))
|
||||
copy(arr, t.value)
|
||||
v.estack.PushVal(&ArrayItem{arr})
|
||||
case *ArrayItem:
|
||||
v.estack.PushVal(t)
|
||||
default:
|
||||
n := item.BigInt().Int64()
|
||||
if n > MaxArraySize {
|
||||
panic("too long array")
|
||||
}
|
||||
typ := AnyT
|
||||
if op == opcode.NEWARRAYT {
|
||||
typ = StackItemType(parameter[0])
|
||||
}
|
||||
items := makeArrayOfType(int(n), typ)
|
||||
v.estack.PushVal(&ArrayItem{items})
|
||||
n := item.BigInt().Int64()
|
||||
if n > MaxArraySize {
|
||||
panic("too long array")
|
||||
}
|
||||
typ := AnyT
|
||||
if op == opcode.NEWARRAYT {
|
||||
typ = StackItemType(parameter[0])
|
||||
}
|
||||
items := makeArrayOfType(int(n), typ)
|
||||
v.estack.PushVal(&ArrayItem{items})
|
||||
|
||||
case opcode.NEWSTRUCT0:
|
||||
v.estack.PushVal(&StructItem{[]StackItem{}})
|
||||
|
||||
case opcode.NEWSTRUCT:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *ArrayItem:
|
||||
arr := make([]StackItem, len(t.value))
|
||||
copy(arr, t.value)
|
||||
v.estack.PushVal(&StructItem{arr})
|
||||
case *StructItem:
|
||||
v.estack.PushVal(t)
|
||||
default:
|
||||
n := item.BigInt().Int64()
|
||||
if n > MaxArraySize {
|
||||
panic("too long struct")
|
||||
}
|
||||
items := makeArrayOfType(int(n), AnyT)
|
||||
v.estack.PushVal(&StructItem{items})
|
||||
n := item.BigInt().Int64()
|
||||
if n > MaxArraySize {
|
||||
panic("too long struct")
|
||||
}
|
||||
items := makeArrayOfType(int(n), AnyT)
|
||||
v.estack.PushVal(&StructItem{items})
|
||||
|
||||
case opcode.APPEND:
|
||||
itemElem := v.estack.Pop()
|
||||
|
|
|
@ -372,7 +372,7 @@ func appendBigStruct(size uint16) []opcode.Opcode {
|
|||
return append(prog,
|
||||
opcode.INITSSLOT, 1,
|
||||
opcode.PUSHINT16, opcode.Opcode(size), opcode.Opcode(size>>8), // LE
|
||||
opcode.PACK, opcode.NEWSTRUCT,
|
||||
opcode.PACK, opcode.CONVERT, opcode.Opcode(StructT),
|
||||
opcode.STSFLD0, opcode.LDSFLD0,
|
||||
opcode.DUP,
|
||||
opcode.PUSH0, opcode.NEWARRAY,
|
||||
|
@ -401,20 +401,19 @@ func TestStackLimit(t *testing.T) {
|
|||
{opcode.NEWARRAY, 3}, // array + 2 items
|
||||
{opcode.STSFLD0, 3},
|
||||
{opcode.LDSFLD0, 4},
|
||||
{opcode.NEWSTRUCT, 6}, // all items are copied
|
||||
{opcode.NEWMAP, 7},
|
||||
{opcode.DUP, 8},
|
||||
{opcode.PUSH2, 9},
|
||||
{opcode.LDSFLD0, 10},
|
||||
{opcode.SETITEM, 8}, // -3 items and 1 new element in map
|
||||
{opcode.DUP, 9},
|
||||
{opcode.PUSH2, 10},
|
||||
{opcode.LDSFLD0, 11},
|
||||
{opcode.SETITEM, 8}, // -3 items and no new elements in map
|
||||
{opcode.DUP, 9},
|
||||
{opcode.PUSH2, 10},
|
||||
{opcode.REMOVE, 7}, // as we have right after NEWMAP
|
||||
{opcode.DROP, 6}, // DROP map with no elements
|
||||
{opcode.NEWMAP, 5},
|
||||
{opcode.DUP, 6},
|
||||
{opcode.PUSH2, 7},
|
||||
{opcode.LDSFLD0, 8},
|
||||
{opcode.SETITEM, 6}, // -3 items and 1 new element in map
|
||||
{opcode.DUP, 7},
|
||||
{opcode.PUSH2, 8},
|
||||
{opcode.LDSFLD0, 9},
|
||||
{opcode.SETITEM, 6}, // -3 items and no new elements in map
|
||||
{opcode.DUP, 7},
|
||||
{opcode.PUSH2, 8},
|
||||
{opcode.REMOVE, 5}, // as we have right after NEWMAP
|
||||
{opcode.DROP, 4}, // DROP map with no elements
|
||||
}
|
||||
|
||||
prog := make([]opcode.Opcode, len(expected)+2)
|
||||
|
@ -1189,10 +1188,6 @@ func TestNEWARRAYArray(t *testing.T) {
|
|||
t.Run("ByteArray", getTestFuncForVM(prog, NewArrayItem([]StackItem{}), []byte{}))
|
||||
t.Run("BadSize", getTestFuncForVM(prog, nil, MaxArraySize+1))
|
||||
t.Run("Integer", getTestFuncForVM(prog, []StackItem{NullItem{}}, 1))
|
||||
|
||||
arr := []StackItem{makeStackItem(42)}
|
||||
t.Run("Array", getTestFuncForVM(prog, arr, arr))
|
||||
t.Run("Struct", getTestFuncForVM(prog, arr, NewStructItem(arr)))
|
||||
}
|
||||
|
||||
func testNEWARRAYIssue437(t *testing.T, i1 opcode.Opcode, t2 StackItemType, appended bool) {
|
||||
|
@ -1244,10 +1239,6 @@ func TestNEWSTRUCT(t *testing.T) {
|
|||
t.Run("ByteArray", getTestFuncForVM(prog, NewStructItem([]StackItem{}), []byte{}))
|
||||
t.Run("BadSize", getTestFuncForVM(prog, nil, MaxArraySize+1))
|
||||
t.Run("Integer", getTestFuncForVM(prog, NewStructItem([]StackItem{NullItem{}}), 1))
|
||||
|
||||
arr := []StackItem{makeStackItem(42)}
|
||||
t.Run("Array", getTestFuncForVM(prog, NewStructItem(arr), NewArrayItem(arr)))
|
||||
t.Run("Struct", getTestFuncForVM(prog, NewStructItem(arr), NewStructItem(arr)))
|
||||
}
|
||||
|
||||
func TestAPPEND(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue