vm: move MaxArraySize and MaxItemSize to stackitem package
This commit is contained in:
parent
349110149f
commit
f2f01a08c9
7 changed files with 38 additions and 37 deletions
|
@ -4,7 +4,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
)
|
)
|
||||||
|
|
||||||
var assignTestCases = []testCase{
|
var assignTestCases = []testCase{
|
||||||
|
@ -144,9 +144,9 @@ func TestManyAssignments(t *testing.T) {
|
||||||
src2 := `return a
|
src2 := `return a
|
||||||
}`
|
}`
|
||||||
|
|
||||||
for i := 0; i < vm.MaxArraySize; i++ {
|
for i := 0; i < stackitem.MaxArraySize; i++ {
|
||||||
src1 += "a += 1\n"
|
src1 += "a += 1\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
eval(t, src1+src2, big.NewInt(vm.MaxArraySize))
|
eval(t, src1+src2, big.NewInt(stackitem.MaxArraySize))
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) {
|
||||||
err = errNoInstParam
|
err = errNoInstParam
|
||||||
} else {
|
} else {
|
||||||
var n = binary.LittleEndian.Uint32(c.prog[c.nextip : c.nextip+4])
|
var n = binary.LittleEndian.Uint32(c.prog[c.nextip : c.nextip+4])
|
||||||
if n > MaxItemSize {
|
if n > stackitem.MaxSize {
|
||||||
return instr, nil, errors.New("parameter is too big")
|
return instr, nil, errors.New("parameter is too big")
|
||||||
}
|
}
|
||||||
numtoread = int(n)
|
numtoread = int(n)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -21,14 +22,14 @@ func getNumOfThingsFromInstr(instr opcode.Opcode, param []byte) (int, bool) {
|
||||||
nthings = int(instr-opcode.PUSH1) + 1
|
nthings = int(instr-opcode.PUSH1) + 1
|
||||||
case instr <= opcode.PUSHINT256:
|
case instr <= opcode.PUSHINT256:
|
||||||
n := bigint.FromBytes(param)
|
n := bigint.FromBytes(param)
|
||||||
if !n.IsInt64() || n.Int64() > MaxArraySize {
|
if !n.IsInt64() || n.Int64() > stackitem.MaxArraySize {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
nthings = int(n.Int64())
|
nthings = int(n.Int64())
|
||||||
default:
|
default:
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
if nthings < 1 || nthings > MaxArraySize {
|
if nthings < 1 || nthings > stackitem.MaxArraySize {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
return nthings, true
|
return nthings, true
|
||||||
|
@ -69,7 +70,7 @@ func ParseMultiSigContract(script []byte) (int, [][]byte, bool) {
|
||||||
}
|
}
|
||||||
pubs = append(pubs, param)
|
pubs = append(pubs, param)
|
||||||
nkeys++
|
nkeys++
|
||||||
if nkeys > MaxArraySize {
|
if nkeys > stackitem.MaxArraySize {
|
||||||
return nsigs, nil, false
|
return nsigs, nil, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ func RuntimeSerialize(vm *VM) error {
|
||||||
data, err := stackitem.SerializeItem(item.value)
|
data, err := stackitem.SerializeItem(item.value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if len(data) > MaxItemSize {
|
} else if len(data) > stackitem.MaxSize {
|
||||||
return errors.New("too big item")
|
return errors.New("too big item")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,12 @@ import (
|
||||||
// MaxBigIntegerSizeBits is the maximum size of BigInt item in bits.
|
// MaxBigIntegerSizeBits is the maximum size of BigInt item in bits.
|
||||||
const MaxBigIntegerSizeBits = 32 * 8
|
const MaxBigIntegerSizeBits = 32 * 8
|
||||||
|
|
||||||
|
// MaxArraySize is the maximum array size allowed in the VM.
|
||||||
|
const MaxArraySize = 1024
|
||||||
|
|
||||||
|
// MaxSize is the maximum item size allowed in the VM.
|
||||||
|
const MaxSize = 1024 * 1024
|
||||||
|
|
||||||
// Item represents the "real" value that is pushed on the stack.
|
// Item represents the "real" value that is pushed on the stack.
|
||||||
type Item interface {
|
type Item interface {
|
||||||
fmt.Stringer
|
fmt.Stringer
|
||||||
|
|
22
pkg/vm/vm.go
22
pkg/vm/vm.go
|
@ -46,12 +46,6 @@ type ScriptHashGetter interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// MaxArraySize is the maximum array size allowed in the VM.
|
|
||||||
MaxArraySize = 1024
|
|
||||||
|
|
||||||
// MaxItemSize is the maximum item size allowed in the VM.
|
|
||||||
MaxItemSize = 1024 * 1024
|
|
||||||
|
|
||||||
// MaxInvocationStackSize is the maximum size of an invocation stack.
|
// MaxInvocationStackSize is the maximum size of an invocation stack.
|
||||||
MaxInvocationStackSize = 1024
|
MaxInvocationStackSize = 1024
|
||||||
|
|
||||||
|
@ -653,7 +647,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
|
|
||||||
case opcode.NEWBUFFER:
|
case opcode.NEWBUFFER:
|
||||||
n := toInt(v.estack.Pop().BigInt())
|
n := toInt(v.estack.Pop().BigInt())
|
||||||
if n < 0 || n > MaxItemSize {
|
if n < 0 || n > stackitem.MaxSize {
|
||||||
panic("invalid size")
|
panic("invalid size")
|
||||||
}
|
}
|
||||||
v.estack.PushVal(stackitem.NewBuffer(make([]byte, n)))
|
v.estack.PushVal(stackitem.NewBuffer(make([]byte, n)))
|
||||||
|
@ -684,7 +678,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
case opcode.CAT:
|
case opcode.CAT:
|
||||||
b := v.estack.Pop().Bytes()
|
b := v.estack.Pop().Bytes()
|
||||||
a := v.estack.Pop().Bytes()
|
a := v.estack.Pop().Bytes()
|
||||||
if l := len(a) + len(b); l > MaxItemSize {
|
if l := len(a) + len(b); l > stackitem.MaxSize {
|
||||||
panic(fmt.Sprintf("too big item: %d", l))
|
panic(fmt.Sprintf("too big item: %d", l))
|
||||||
}
|
}
|
||||||
ab := append(a, b...)
|
ab := append(a, b...)
|
||||||
|
@ -1001,7 +995,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
case opcode.NEWARRAY, opcode.NEWARRAYT:
|
case opcode.NEWARRAY, opcode.NEWARRAYT:
|
||||||
item := v.estack.Pop()
|
item := v.estack.Pop()
|
||||||
n := item.BigInt().Int64()
|
n := item.BigInt().Int64()
|
||||||
if n > MaxArraySize {
|
if n > stackitem.MaxArraySize {
|
||||||
panic("too long array")
|
panic("too long array")
|
||||||
}
|
}
|
||||||
typ := stackitem.AnyT
|
typ := stackitem.AnyT
|
||||||
|
@ -1017,7 +1011,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
case opcode.NEWSTRUCT:
|
case opcode.NEWSTRUCT:
|
||||||
item := v.estack.Pop()
|
item := v.estack.Pop()
|
||||||
n := item.BigInt().Int64()
|
n := item.BigInt().Int64()
|
||||||
if n > MaxArraySize {
|
if n > stackitem.MaxArraySize {
|
||||||
panic("too long struct")
|
panic("too long struct")
|
||||||
}
|
}
|
||||||
items := makeArrayOfType(int(n), stackitem.AnyT)
|
items := makeArrayOfType(int(n), stackitem.AnyT)
|
||||||
|
@ -1031,12 +1025,12 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
|
|
||||||
switch t := arrElem.value.(type) {
|
switch t := arrElem.value.(type) {
|
||||||
case *stackitem.Array:
|
case *stackitem.Array:
|
||||||
if t.Len() >= MaxArraySize {
|
if t.Len() >= stackitem.MaxArraySize {
|
||||||
panic("too long array")
|
panic("too long array")
|
||||||
}
|
}
|
||||||
t.Append(val)
|
t.Append(val)
|
||||||
case *stackitem.Struct:
|
case *stackitem.Struct:
|
||||||
if t.Len() >= MaxArraySize {
|
if t.Len() >= stackitem.MaxArraySize {
|
||||||
panic("too long struct")
|
panic("too long struct")
|
||||||
}
|
}
|
||||||
t.Append(val)
|
t.Append(val)
|
||||||
|
@ -1048,7 +1042,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
|
|
||||||
case opcode.PACK:
|
case opcode.PACK:
|
||||||
n := int(v.estack.Pop().BigInt().Int64())
|
n := int(v.estack.Pop().BigInt().Int64())
|
||||||
if n < 0 || n > v.estack.Len() || n > MaxArraySize {
|
if n < 0 || n > v.estack.Len() || n > stackitem.MaxArraySize {
|
||||||
panic("OPACK: invalid length")
|
panic("OPACK: invalid length")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,7 +1113,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
case *stackitem.Map:
|
case *stackitem.Map:
|
||||||
if i := t.Index(key.value); i >= 0 {
|
if i := t.Index(key.value); i >= 0 {
|
||||||
v.refs.Remove(t.Value().([]stackitem.MapElement)[i].Value)
|
v.refs.Remove(t.Value().([]stackitem.MapElement)[i].Value)
|
||||||
} else if t.Len() >= MaxArraySize {
|
} else if t.Len() >= stackitem.MaxArraySize {
|
||||||
panic("too big map")
|
panic("too big map")
|
||||||
}
|
}
|
||||||
t.Add(key.value, item)
|
t.Add(key.value, item)
|
||||||
|
|
|
@ -489,9 +489,9 @@ func TestPUSHDATA4(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPushData4BigN(t *testing.T) {
|
func TestPushData4BigN(t *testing.T) {
|
||||||
prog := make([]byte, 1+4+MaxItemSize+1)
|
prog := make([]byte, 1+4+stackitem.MaxSize+1)
|
||||||
prog[0] = byte(opcode.PUSHDATA4)
|
prog[0] = byte(opcode.PUSHDATA4)
|
||||||
binary.LittleEndian.PutUint32(prog[1:], MaxItemSize+1)
|
binary.LittleEndian.PutUint32(prog[1:], stackitem.MaxSize+1)
|
||||||
|
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
checkVMFailed(t, vm)
|
checkVMFailed(t, vm)
|
||||||
|
@ -1222,7 +1222,7 @@ func TestNEWBUFFER(t *testing.T) {
|
||||||
prog := makeProgram(opcode.NEWBUFFER)
|
prog := makeProgram(opcode.NEWBUFFER)
|
||||||
t.Run("Good", getTestFuncForVM(prog, stackitem.NewBuffer([]byte{0, 0, 0}), 3))
|
t.Run("Good", getTestFuncForVM(prog, stackitem.NewBuffer([]byte{0, 0, 0}), 3))
|
||||||
t.Run("Negative", getTestFuncForVM(prog, nil, -1))
|
t.Run("Negative", getTestFuncForVM(prog, nil, -1))
|
||||||
t.Run("TooBig", getTestFuncForVM(prog, nil, MaxItemSize+1))
|
t.Run("TooBig", getTestFuncForVM(prog, nil, stackitem.MaxSize+1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMEMCPY(t *testing.T) {
|
func TestMEMCPY(t *testing.T) {
|
||||||
|
@ -1251,7 +1251,7 @@ func TestNEWSTRUCT0(t *testing.T) {
|
||||||
func TestNEWARRAYArray(t *testing.T) {
|
func TestNEWARRAYArray(t *testing.T) {
|
||||||
prog := makeProgram(opcode.NEWARRAY)
|
prog := makeProgram(opcode.NEWARRAY)
|
||||||
t.Run("ByteArray", getTestFuncForVM(prog, stackitem.NewArray([]stackitem.Item{}), []byte{}))
|
t.Run("ByteArray", getTestFuncForVM(prog, stackitem.NewArray([]stackitem.Item{}), []byte{}))
|
||||||
t.Run("BadSize", getTestFuncForVM(prog, nil, MaxArraySize+1))
|
t.Run("BadSize", getTestFuncForVM(prog, nil, stackitem.MaxArraySize+1))
|
||||||
t.Run("Integer", getTestFuncForVM(prog, []stackitem.Item{stackitem.Null{}}, 1))
|
t.Run("Integer", getTestFuncForVM(prog, []stackitem.Item{stackitem.Null{}}, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1302,7 +1302,7 @@ func TestNEWARRAYT(t *testing.T) {
|
||||||
func TestNEWSTRUCT(t *testing.T) {
|
func TestNEWSTRUCT(t *testing.T) {
|
||||||
prog := makeProgram(opcode.NEWSTRUCT)
|
prog := makeProgram(opcode.NEWSTRUCT)
|
||||||
t.Run("ByteArray", getTestFuncForVM(prog, stackitem.NewStruct([]stackitem.Item{}), []byte{}))
|
t.Run("ByteArray", getTestFuncForVM(prog, stackitem.NewStruct([]stackitem.Item{}), []byte{}))
|
||||||
t.Run("BadSize", getTestFuncForVM(prog, nil, MaxArraySize+1))
|
t.Run("BadSize", getTestFuncForVM(prog, nil, stackitem.MaxArraySize+1))
|
||||||
t.Run("Integer", getTestFuncForVM(prog, stackitem.NewStruct([]stackitem.Item{stackitem.Null{}}), 1))
|
t.Run("Integer", getTestFuncForVM(prog, stackitem.NewStruct([]stackitem.Item{stackitem.Null{}}), 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1330,15 +1330,15 @@ func TestAPPENDBad(t *testing.T) {
|
||||||
func TestAPPENDGoodSizeLimit(t *testing.T) {
|
func TestAPPENDGoodSizeLimit(t *testing.T) {
|
||||||
prog := makeProgram(opcode.NEWARRAY, opcode.DUP, opcode.PUSH0, opcode.APPEND)
|
prog := makeProgram(opcode.NEWARRAY, opcode.DUP, opcode.PUSH0, opcode.APPEND)
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
vm.estack.PushVal(MaxArraySize - 1)
|
vm.estack.PushVal(stackitem.MaxArraySize - 1)
|
||||||
runVM(t, vm)
|
runVM(t, vm)
|
||||||
assert.Equal(t, 1, vm.estack.Len())
|
assert.Equal(t, 1, vm.estack.Len())
|
||||||
assert.Equal(t, MaxArraySize, len(vm.estack.Pop().Array()))
|
assert.Equal(t, stackitem.MaxArraySize, len(vm.estack.Pop().Array()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPPENDBadSizeLimit(t *testing.T) {
|
func TestAPPENDBadSizeLimit(t *testing.T) {
|
||||||
prog := makeProgram(opcode.NEWARRAY, opcode.DUP, opcode.PUSH0, opcode.APPEND)
|
prog := makeProgram(opcode.NEWARRAY, opcode.DUP, opcode.PUSH0, opcode.APPEND)
|
||||||
runWithArgs(t, prog, nil, MaxArraySize)
|
runWithArgs(t, prog, nil, stackitem.MaxArraySize)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPICKITEM(t *testing.T) {
|
func TestPICKITEM(t *testing.T) {
|
||||||
|
@ -1399,11 +1399,11 @@ func TestSETITEMMap(t *testing.T) {
|
||||||
func TestSETITEMBigMapBad(t *testing.T) {
|
func TestSETITEMBigMapBad(t *testing.T) {
|
||||||
prog := makeProgram(opcode.SETITEM)
|
prog := makeProgram(opcode.SETITEM)
|
||||||
m := stackitem.NewMap()
|
m := stackitem.NewMap()
|
||||||
for i := 0; i < MaxArraySize; i++ {
|
for i := 0; i < stackitem.MaxArraySize; i++ {
|
||||||
m.Add(stackitem.Make(i), stackitem.Make(i))
|
m.Add(stackitem.Make(i), stackitem.Make(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
runWithArgs(t, prog, nil, m, MaxArraySize, 0)
|
runWithArgs(t, prog, nil, m, stackitem.MaxArraySize, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test checks is SETITEM properly updates reference counter.
|
// This test checks is SETITEM properly updates reference counter.
|
||||||
|
@ -1411,7 +1411,7 @@ func TestSETITEMBigMapBad(t *testing.T) {
|
||||||
// 2. SETITEM each of them to a map.
|
// 2. SETITEM each of them to a map.
|
||||||
// 3. Replace each of them with a scalar value.
|
// 3. Replace each of them with a scalar value.
|
||||||
func TestSETITEMMapStackLimit(t *testing.T) {
|
func TestSETITEMMapStackLimit(t *testing.T) {
|
||||||
size := MaxArraySize - 3
|
size := stackitem.MaxArraySize - 3
|
||||||
m := stackitem.NewMap()
|
m := stackitem.NewMap()
|
||||||
m.Add(stackitem.NewBigInteger(big.NewInt(1)), stackitem.NewArray(makeArrayOfType(size, stackitem.BooleanT)))
|
m.Add(stackitem.NewBigInteger(big.NewInt(1)), stackitem.NewArray(makeArrayOfType(size, stackitem.BooleanT)))
|
||||||
m.Add(stackitem.NewBigInteger(big.NewInt(2)), stackitem.NewArray(makeArrayOfType(size, stackitem.BooleanT)))
|
m.Add(stackitem.NewBigInteger(big.NewInt(2)), stackitem.NewArray(makeArrayOfType(size, stackitem.BooleanT)))
|
||||||
|
@ -1431,7 +1431,7 @@ func TestSETITEMBigMapGood(t *testing.T) {
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
|
|
||||||
m := stackitem.NewMap()
|
m := stackitem.NewMap()
|
||||||
for i := 0; i < MaxArraySize; i++ {
|
for i := 0; i < stackitem.MaxArraySize; i++ {
|
||||||
m.Add(stackitem.Make(i), stackitem.Make(i))
|
m.Add(stackitem.Make(i), stackitem.Make(i))
|
||||||
}
|
}
|
||||||
vm.estack.Push(&Element{value: m})
|
vm.estack.Push(&Element{value: m})
|
||||||
|
@ -1842,7 +1842,7 @@ func TestCAT(t *testing.T) {
|
||||||
t.Run("NoArgument", getTestFuncForVM(prog, nil))
|
t.Run("NoArgument", getTestFuncForVM(prog, nil))
|
||||||
t.Run("OneArgument", getTestFuncForVM(prog, nil, []byte("abc")))
|
t.Run("OneArgument", getTestFuncForVM(prog, nil, []byte("abc")))
|
||||||
t.Run("BigItem", func(t *testing.T) {
|
t.Run("BigItem", func(t *testing.T) {
|
||||||
arg := make([]byte, MaxItemSize/2+1)
|
arg := make([]byte, stackitem.MaxSize/2+1)
|
||||||
runWithArgs(t, prog, nil, arg, arg)
|
runWithArgs(t, prog, nil, arg, arg)
|
||||||
})
|
})
|
||||||
t.Run("Good", getTestFuncForVM(prog, stackitem.NewBuffer([]byte("abcdef")), []byte("abc"), []byte("def")))
|
t.Run("Good", getTestFuncForVM(prog, stackitem.NewBuffer([]byte("abcdef")), []byte("abc"), []byte("def")))
|
||||||
|
@ -1900,10 +1900,10 @@ func TestPACK(t *testing.T) {
|
||||||
func TestPACKBigLen(t *testing.T) {
|
func TestPACKBigLen(t *testing.T) {
|
||||||
prog := makeProgram(opcode.PACK)
|
prog := makeProgram(opcode.PACK)
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
for i := 0; i <= MaxArraySize; i++ {
|
for i := 0; i <= stackitem.MaxArraySize; i++ {
|
||||||
vm.estack.PushVal(0)
|
vm.estack.PushVal(0)
|
||||||
}
|
}
|
||||||
vm.estack.PushVal(MaxArraySize + 1)
|
vm.estack.PushVal(stackitem.MaxArraySize + 1)
|
||||||
checkVMFailed(t, vm)
|
checkVMFailed(t, vm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue