Merge pull request #791 from nspcc-dev/fix/calli

vm: fix offset for CALLI opcode
This commit is contained in:
Roman Khimov 2020-03-26 13:13:28 +03:00 committed by GitHub
commit 198fffb9b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1118,7 +1118,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
v.estack.PushVal(len(arr)) v.estack.PushVal(len(arr))
case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT: case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT:
offset := v.getJumpOffset(ctx, parameter) offset := v.getJumpOffset(ctx, parameter, 0)
cond := true cond := true
if op != opcode.JMP { if op != opcode.JMP {
cond = v.estack.Pop().Bool() == (op == opcode.JMPIF) cond = v.estack.Pop().Bool() == (op == opcode.JMPIF)
@ -1133,7 +1133,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
newCtx.rvcount = -1 newCtx.rvcount = -1
v.istack.PushVal(newCtx) v.istack.PushVal(newCtx)
offset := v.getJumpOffset(newCtx, parameter) offset := v.getJumpOffset(newCtx, parameter, 0)
v.jumpIf(newCtx, offset, true) v.jumpIf(newCtx, offset, true)
case opcode.SYSCALL: case opcode.SYSCALL:
@ -1388,7 +1388,9 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
v.estack = newCtx.estack v.estack = newCtx.estack
v.astack = newCtx.astack v.astack = newCtx.astack
if op == opcode.CALLI { if op == opcode.CALLI {
offset := v.getJumpOffset(newCtx, parameter[2:]) // CALLI is a bit different from other JMPs
// https://github.com/neo-project/neo-vm/blob/master-2.x/src/neo-vm/ExecutionEngine.cs#L1175
offset := v.getJumpOffset(newCtx, parameter[2:], 2)
v.jumpIf(newCtx, offset, true) v.jumpIf(newCtx, offset, true)
} }
@ -1416,9 +1418,9 @@ func (v *VM) jumpIf(ctx *Context, offset int, cond bool) {
// getJumpOffset returns instruction number in a current context // getJumpOffset returns instruction number in a current context
// to a which JMP should be performed. // to a which JMP should be performed.
// parameter is interpreted as little-endian int16. // parameter is interpreted as little-endian int16.
func (v *VM) getJumpOffset(ctx *Context, parameter []byte) int { func (v *VM) getJumpOffset(ctx *Context, parameter []byte, mod int) int {
rOffset := int16(binary.LittleEndian.Uint16(parameter)) rOffset := int16(binary.LittleEndian.Uint16(parameter))
offset := ctx.ip + int(rOffset) offset := ctx.ip + int(rOffset) + mod
if offset < 0 || offset > len(ctx.prog) { if offset < 0 || offset > len(ctx.prog) {
panic(fmt.Sprintf("JMP: invalid offset %d ip at %d", offset, ctx.ip)) panic(fmt.Sprintf("JMP: invalid offset %d ip at %d", offset, ctx.ip))
} }