Skip to content

Commit 5924123

Browse files
authored
Merge pull request #1939 from nspcc-dev/vm-arith-null
Allow NULL items for LT/LE/GT/GE instructions
2 parents 62810bb + 8fa4a57 commit 5924123

File tree

8 files changed

+76
-62
lines changed

8 files changed

+76
-62
lines changed

pkg/compiler/codegen.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1901,11 +1901,11 @@ func convertToken(tok token.Token, typ types.Type) (opcode.Opcode, error) {
19011901
case token.LSS:
19021902
return opcode.LT, nil
19031903
case token.LEQ:
1904-
return opcode.LTE, nil
1904+
return opcode.LE, nil
19051905
case token.GTR:
19061906
return opcode.GT, nil
19071907
case token.GEQ:
1908-
return opcode.GTE, nil
1908+
return opcode.GE, nil
19091909
case token.EQL:
19101910
// VM has separate opcodes for number and string equality
19111911
if isNumber(typ) {

pkg/core/fee/opcode.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ var coefficients = map[opcode.Opcode]int64{
173173
opcode.NUMEQUAL: 1 << 3,
174174
opcode.NUMNOTEQUAL: 1 << 3,
175175
opcode.LT: 1 << 3,
176-
opcode.LTE: 1 << 3,
176+
opcode.LE: 1 << 3,
177177
opcode.GT: 1 << 3,
178-
opcode.GTE: 1 << 3,
178+
opcode.GE: 1 << 3,
179179
opcode.MIN: 1 << 3,
180180
opcode.MAX: 1 << 3,
181181
opcode.WITHIN: 1 << 3,

pkg/vm/opcode/opcode.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,9 @@ const (
188188
NUMEQUAL Opcode = 0xB3
189189
NUMNOTEQUAL Opcode = 0xB4
190190
LT Opcode = 0xB5
191-
LTE Opcode = 0xB6
191+
LE Opcode = 0xB6
192192
GT Opcode = 0xB7
193-
GTE Opcode = 0xB8
193+
GE Opcode = 0xB8
194194
MIN Opcode = 0xB9
195195
MAX Opcode = 0xBA
196196
WITHIN Opcode = 0xBB

pkg/vm/opcode/opcode_string.go

+31-31
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/vm/opcodebench_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ func BenchmarkOpcodes(t *testing.B) {
571571
}
572572
binaries := []opcode.Opcode{opcode.AND, opcode.OR, opcode.XOR, opcode.ADD, opcode.SUB,
573573
opcode.BOOLAND, opcode.BOOLOR, opcode.NUMEQUAL, opcode.NUMNOTEQUAL,
574-
opcode.LT, opcode.LTE, opcode.GT, opcode.GTE, opcode.MIN, opcode.MAX}
574+
opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX}
575575
for _, op := range binaries {
576576
t.Run(op.String(), func(t *testing.B) {
577577
t.Run("0+0", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 0, 0)) })

pkg/vm/testdata/neo-vm

Submodule neo-vm updated 51 files

pkg/vm/vm.go

+21-19
Original file line numberDiff line numberDiff line change
@@ -972,25 +972,27 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
972972
a := v.estack.Pop().BigInt()
973973
v.estack.PushVal(a.Cmp(b) != 0)
974974

975-
case opcode.LT:
976-
b := v.estack.Pop().BigInt()
977-
a := v.estack.Pop().BigInt()
978-
v.estack.PushVal(a.Cmp(b) == -1)
979-
980-
case opcode.LTE:
981-
b := v.estack.Pop().BigInt()
982-
a := v.estack.Pop().BigInt()
983-
v.estack.PushVal(a.Cmp(b) <= 0)
984-
985-
case opcode.GT:
986-
b := v.estack.Pop().BigInt()
987-
a := v.estack.Pop().BigInt()
988-
v.estack.PushVal(a.Cmp(b) == 1)
989-
990-
case opcode.GTE:
991-
b := v.estack.Pop().BigInt()
992-
a := v.estack.Pop().BigInt()
993-
v.estack.PushVal(a.Cmp(b) >= 0)
975+
case opcode.LT, opcode.LE, opcode.GT, opcode.GE:
976+
eb := v.estack.Pop()
977+
ea := v.estack.Pop()
978+
_, aNil := ea.Item().(stackitem.Null)
979+
_, bNil := eb.Item().(stackitem.Null)
980+
981+
res := !aNil && !bNil
982+
if res {
983+
cmp := ea.BigInt().Cmp(eb.BigInt())
984+
switch op {
985+
case opcode.LT:
986+
res = cmp == -1
987+
case opcode.LE:
988+
res = cmp <= 0
989+
case opcode.GT:
990+
res = cmp == 1
991+
case opcode.GE:
992+
res = cmp >= 0
993+
}
994+
}
995+
v.estack.PushVal(res)
994996

995997
case opcode.MIN:
996998
b := v.estack.Pop().BigInt()

pkg/vm/vm_test.go

+16-4
Original file line numberDiff line numberDiff line change
@@ -807,13 +807,25 @@ func TestSHL(t *testing.T) {
807807
t.Run("BigResult", getTestFuncForVM(prog, nil, getBigInt(stackitem.MaxBigIntegerSizeBits/2, 0), stackitem.MaxBigIntegerSizeBits/2))
808808
}
809809

810+
func TestArithNullArg(t *testing.T) {
811+
for _, op := range []opcode.Opcode{opcode.LT, opcode.LE, opcode.GT, opcode.GE} {
812+
prog := makeProgram(op)
813+
t.Run(op.String(), func(t *testing.T) {
814+
runWithArgs(t, prog, false, stackitem.Null{}, 0)
815+
runWithArgs(t, prog, false, 0, stackitem.Null{})
816+
runWithArgs(t, prog, nil, stackitem.NewInterop(nil), 1) // also has `.Value() == nil`
817+
})
818+
819+
}
820+
}
821+
810822
func TestLT(t *testing.T) {
811823
prog := makeProgram(opcode.LT)
812824
runWithArgs(t, prog, false, 4, 3)
813825
}
814826

815-
func TestLTE(t *testing.T) {
816-
prog := makeProgram(opcode.LTE)
827+
func TestLE(t *testing.T) {
828+
prog := makeProgram(opcode.LE)
817829
runWithArgs(t, prog, true, 2, 3)
818830
}
819831

@@ -822,8 +834,8 @@ func TestGT(t *testing.T) {
822834
runWithArgs(t, prog, true, 9, 3)
823835
}
824836

825-
func TestGTE(t *testing.T) {
826-
prog := makeProgram(opcode.GTE)
837+
func TestGE(t *testing.T) {
838+
prog := makeProgram(opcode.GE)
827839
runWithArgs(t, prog, true, 3, 3)
828840
}
829841

0 commit comments

Comments
 (0)