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:
Evgenii Stratonikov 2020-05-20 17:09:57 +03:00
parent 1a0290edc6
commit 063c29636b
2 changed files with 28 additions and 55 deletions

View file

@ -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()

View file

@ -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) {