From 70f0c656b03fb51bc1376d66d142c8355bf6b8d7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 29 Apr 2020 17:13:46 +0300 Subject: [PATCH] vm: check Integer size on creation --- pkg/vm/stack_item.go | 13 +++++++++---- pkg/vm/vm.go | 23 ----------------------- pkg/vm/vm_test.go | 41 ----------------------------------------- 3 files changed, 9 insertions(+), 68 deletions(-) diff --git a/pkg/vm/stack_item.go b/pkg/vm/stack_item.go index bca4e2745..bba8b8fc3 100644 --- a/pkg/vm/stack_item.go +++ b/pkg/vm/stack_item.go @@ -85,9 +85,7 @@ func makeStackItem(v interface{}) StackItem { value: val, } case *big.Int: - return &BigIntegerItem{ - value: val, - } + return NewBigIntegerItem(val) case StackItem: return val case []int: @@ -311,6 +309,9 @@ type BigIntegerItem struct { // NewBigIntegerItem returns an new BigIntegerItem object. func NewBigIntegerItem(value *big.Int) *BigIntegerItem { + if value.BitLen() > MaxBigIntegerSizeBits { + panic("integer is too big") + } return &BigIntegerItem{ value: value, } @@ -519,7 +520,11 @@ func (i *ByteArrayItem) TryBytes() ([]byte, error) { // TryInteger implements StackItem interface. func (i *ByteArrayItem) TryInteger() (*big.Int, error) { - return emit.BytesToInt(i.value), nil + bi := emit.BytesToInt(i.value) + if bi.BitLen() > MaxBigIntegerSizeBits { + return nil, errors.New("integer is too big") + } + return bi, nil } // Equals implements StackItem interface. diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 6d4051749..721dd3247 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -775,58 +775,43 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro case opcode.INC: x := v.estack.Pop().BigInt() a := new(big.Int).Add(x, big.NewInt(1)) - v.checkBigIntSize(a) v.estack.PushVal(a) case opcode.DEC: x := v.estack.Pop().BigInt() a := new(big.Int).Sub(x, big.NewInt(1)) - v.checkBigIntSize(a) v.estack.PushVal(a) case opcode.ADD: a := v.estack.Pop().BigInt() - v.checkBigIntSize(a) b := v.estack.Pop().BigInt() - v.checkBigIntSize(b) c := new(big.Int).Add(a, b) - v.checkBigIntSize(c) v.estack.PushVal(c) case opcode.SUB: b := v.estack.Pop().BigInt() - v.checkBigIntSize(b) a := v.estack.Pop().BigInt() - v.checkBigIntSize(a) c := new(big.Int).Sub(a, b) - v.checkBigIntSize(c) v.estack.PushVal(c) case opcode.MUL: a := v.estack.Pop().BigInt() - v.checkBigIntSize(a) b := v.estack.Pop().BigInt() - v.checkBigIntSize(b) c := new(big.Int).Mul(a, b) - v.checkBigIntSize(c) v.estack.PushVal(c) case opcode.DIV: b := v.estack.Pop().BigInt() - v.checkBigIntSize(b) a := v.estack.Pop().BigInt() - v.checkBigIntSize(a) v.estack.PushVal(new(big.Int).Quo(a, b)) case opcode.MOD: b := v.estack.Pop().BigInt() - v.checkBigIntSize(b) a := v.estack.Pop().BigInt() - v.checkBigIntSize(a) v.estack.PushVal(new(big.Int).Rem(a, b)) @@ -838,7 +823,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic(fmt.Sprintf("operand must be between %d and %d", 0, maxSHLArg)) } a := v.estack.Pop().BigInt() - v.checkBigIntSize(a) var item big.Int if op == opcode.SHL { @@ -847,7 +831,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro item.Rsh(a, uint(b)) } - v.checkBigIntSize(&item) v.estack.PushVal(&item) case opcode.NOT: @@ -1527,12 +1510,6 @@ func (v *VM) checkInvocationStackSize() { } } -func (v *VM) checkBigIntSize(a *big.Int) { - if a.BitLen() > MaxBigIntegerSizeBits { - panic("big integer is too big") - } -} - // bytesToPublicKey is a helper deserializing keys using cache and panicing on // error. func (v *VM) bytesToPublicKey(b []byte) *keys.PublicKey { diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 2774ad9d8..a5922cdfa 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -1067,31 +1067,6 @@ func TestADDBigResult(t *testing.T) { checkVMFailed(t, vm) } -func testBigArgument(t *testing.T, inst opcode.Opcode) { - prog := makeProgram(inst) - x := getBigInt(MaxBigIntegerSizeBits, 0) - t.Run(inst.String()+" big 1-st argument", func(t *testing.T) { - vm := load(prog) - vm.estack.PushVal(x) - vm.estack.PushVal(0) - checkVMFailed(t, vm) - }) - t.Run(inst.String()+" big 2-nd argument", func(t *testing.T) { - vm := load(prog) - vm.estack.PushVal(0) - vm.estack.PushVal(x) - checkVMFailed(t, vm) - }) -} - -func TestArithBigArgument(t *testing.T) { - testBigArgument(t, opcode.ADD) - testBigArgument(t, opcode.SUB) - testBigArgument(t, opcode.MUL) - testBigArgument(t, opcode.DIV) - testBigArgument(t, opcode.MOD) -} - func TestMul(t *testing.T) { prog := makeProgram(opcode.MUL) vm := load(prog) @@ -1190,14 +1165,6 @@ func TestSHRNegative(t *testing.T) { checkVMFailed(t, vm) } -func TestSHRBigArgument(t *testing.T) { - prog := makeProgram(opcode.SHR) - vm := load(prog) - vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, 0)) - vm.estack.PushVal(1) - checkVMFailed(t, vm) -} - func TestSHLGood(t *testing.T) { prog := makeProgram(opcode.SHL) vm := load(prog) @@ -1234,14 +1201,6 @@ func TestSHLBigResult(t *testing.T) { checkVMFailed(t, vm) } -func TestSHLBigArgument(t *testing.T) { - prog := makeProgram(opcode.SHR) - vm := load(prog) - vm.estack.PushVal(getBigInt(MaxBigIntegerSizeBits, 0)) - vm.estack.PushVal(1) - checkVMFailed(t, vm) -} - func TestLT(t *testing.T) { prog := makeProgram(opcode.LT) vm := load(prog)