diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 94402f187..46f106482 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -972,25 +972,27 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro a := v.estack.Pop().BigInt() v.estack.PushVal(a.Cmp(b) != 0) - case opcode.LT: - b := v.estack.Pop().BigInt() - a := v.estack.Pop().BigInt() - v.estack.PushVal(a.Cmp(b) == -1) + case opcode.LT, opcode.LE, opcode.GT, opcode.GE: + eb := v.estack.Pop() + ea := v.estack.Pop() + _, aNil := ea.Item().(stackitem.Null) + _, bNil := eb.Item().(stackitem.Null) - case opcode.LE: - b := v.estack.Pop().BigInt() - a := v.estack.Pop().BigInt() - v.estack.PushVal(a.Cmp(b) <= 0) - - case opcode.GT: - b := v.estack.Pop().BigInt() - a := v.estack.Pop().BigInt() - v.estack.PushVal(a.Cmp(b) == 1) - - case opcode.GE: - b := v.estack.Pop().BigInt() - a := v.estack.Pop().BigInt() - v.estack.PushVal(a.Cmp(b) >= 0) + res := !aNil && !bNil + if res { + cmp := ea.BigInt().Cmp(eb.BigInt()) + switch op { + case opcode.LT: + res = cmp == -1 + case opcode.LE: + res = cmp <= 0 + case opcode.GT: + res = cmp == 1 + case opcode.GE: + res = cmp >= 0 + } + } + v.estack.PushVal(res) case opcode.MIN: b := v.estack.Pop().BigInt() diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 87060fe09..5fcaaa89c 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -807,6 +807,18 @@ func TestSHL(t *testing.T) { t.Run("BigResult", getTestFuncForVM(prog, nil, getBigInt(stackitem.MaxBigIntegerSizeBits/2, 0), stackitem.MaxBigIntegerSizeBits/2)) } +func TestArithNullArg(t *testing.T) { + for _, op := range []opcode.Opcode{opcode.LT, opcode.LE, opcode.GT, opcode.GE} { + prog := makeProgram(op) + t.Run(op.String(), func(t *testing.T) { + runWithArgs(t, prog, false, stackitem.Null{}, 0) + runWithArgs(t, prog, false, 0, stackitem.Null{}) + runWithArgs(t, prog, nil, stackitem.NewInterop(nil), 1) // also has `.Value() == nil` + }) + + } +} + func TestLT(t *testing.T) { prog := makeProgram(opcode.LT) runWithArgs(t, prog, false, 4, 3)