vm: check Integer size on creation
This commit is contained in:
parent
a64a0f2681
commit
70f0c656b0
3 changed files with 9 additions and 68 deletions
|
@ -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.
|
||||
|
|
23
pkg/vm/vm.go
23
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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue