From 709f656bcf8e583f6b1a351f81120f01553d2c0e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 26 Jun 2020 19:17:17 +0300 Subject: [PATCH 1/3] vm: remove unused parameter from getJumpOffset --- pkg/vm/vm.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 90d16014b..223a6e078 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -1218,7 +1218,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro opcode.JMPEQ, opcode.JMPEQL, opcode.JMPNE, opcode.JMPNEL, opcode.JMPGT, opcode.JMPGTL, opcode.JMPGE, opcode.JMPGEL, opcode.JMPLT, opcode.JMPLTL, opcode.JMPLE, opcode.JMPLEL: - offset := v.getJumpOffset(ctx, parameter, 0) + offset := v.getJumpOffset(ctx, parameter) cond := true switch op { case opcode.JMP, opcode.JMPL: @@ -1240,7 +1240,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro newCtx.rvcount = -1 v.istack.PushVal(newCtx) - offset := v.getJumpOffset(newCtx, parameter, 0) + offset := v.getJumpOffset(newCtx, parameter) v.jumpIf(newCtx, offset, true) case opcode.CALLA: @@ -1423,7 +1423,7 @@ func (v *VM) jumpIf(ctx *Context, offset int, cond bool) { // to a which JMP should be performed. // parameter should have length either 1 or 4 and // is interpreted as little-endian. -func (v *VM) getJumpOffset(ctx *Context, parameter []byte, mod int) int { +func (v *VM) getJumpOffset(ctx *Context, parameter []byte) int { var rOffset int32 switch l := len(parameter); l { case 1: @@ -1433,7 +1433,7 @@ func (v *VM) getJumpOffset(ctx *Context, parameter []byte, mod int) int { default: panic(fmt.Sprintf("invalid JMP* parameter length: %d", l)) } - offset := ctx.ip + int(rOffset) + mod + offset := ctx.ip + int(rOffset) if offset < 0 || offset > len(ctx.prog) { panic(fmt.Sprintf("JMP: invalid offset %d ip at %d", offset, ctx.ip)) } From 82417499d7efb14329b1bd0dbd3d1233150880d4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 26 Jun 2020 19:27:14 +0300 Subject: [PATCH 2/3] vm: beautify PrintOps() output for JMP* instructions --- pkg/vm/vm.go | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 223a6e078..aa56117d0 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -197,9 +197,18 @@ func (v *VM) PrintOps() { var desc = "" if parameter != nil { switch instr { - case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT, opcode.CALL: - offset := int16(binary.LittleEndian.Uint16(parameter)) - desc = fmt.Sprintf("%d (%d/%x)", ctx.ip+int(offset), offset, parameter) + case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT, opcode.CALL, + opcode.JMPEQ, opcode.JMPNE, + opcode.JMPGT, opcode.JMPGE, opcode.JMPLE, opcode.JMPLT, + opcode.JMPL, opcode.JMPIFL, opcode.JMPIFNOTL, opcode.CALLL, + opcode.JMPEQL, opcode.JMPNEL, + opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLEL, opcode.JMPLTL: + offset, rOffset, err := v.calcJumpOffset(ctx, parameter) + if err != nil { + desc = fmt.Sprintf("ERROR: %v", err) + } else { + desc = fmt.Sprintf("%d (%d/%x)", offset, rOffset, parameter) + } case opcode.PUSHA: offset := int32(binary.LittleEndian.Uint32(parameter)) desc = fmt.Sprintf("%d (%x)", offset, parameter) @@ -1424,6 +1433,14 @@ func (v *VM) jumpIf(ctx *Context, offset int, cond bool) { // parameter should have length either 1 or 4 and // is interpreted as little-endian. func (v *VM) getJumpOffset(ctx *Context, parameter []byte) int { + offset, _, err := v.calcJumpOffset(ctx, parameter) + if err != nil { + panic(err) + } + return offset +} + +func (v *VM) calcJumpOffset(ctx *Context, parameter []byte) (int, int, error) { var rOffset int32 switch l := len(parameter); l { case 1: @@ -1431,14 +1448,14 @@ func (v *VM) getJumpOffset(ctx *Context, parameter []byte) int { case 4: rOffset = int32(binary.LittleEndian.Uint32(parameter)) default: - panic(fmt.Sprintf("invalid JMP* parameter length: %d", l)) + return 0, 0, fmt.Errorf("invalid JMP* parameter length: %d", l) } offset := ctx.ip + int(rOffset) if offset < 0 || offset > len(ctx.prog) { - panic(fmt.Sprintf("JMP: invalid offset %d ip at %d", offset, ctx.ip)) + return 0, 0, fmt.Errorf("invalid offset %d ip at %d", offset, ctx.ip) } - return offset + return offset, int(rOffset), nil } // CheckMultisigPar checks if sigs contains sufficient valid signatures. From bdaffe75cb82f21962d3a1d6cf2c7b4c2c0745f4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 26 Jun 2020 19:34:49 +0300 Subject: [PATCH 3/3] vm: extend PrintOps() with INITSSLOT & INITSLOT --- pkg/vm/vm.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index aa56117d0..61cbc4004 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -212,6 +212,10 @@ func (v *VM) PrintOps() { case opcode.PUSHA: offset := int32(binary.LittleEndian.Uint32(parameter)) desc = fmt.Sprintf("%d (%x)", offset, parameter) + case opcode.INITSSLOT: + desc = fmt.Sprint(parameter[0]) + case opcode.INITSLOT: + desc = fmt.Sprintf("%d local, %d arg", parameter[0], parameter[1]) case opcode.SYSCALL: desc = fmt.Sprintf("%q", parameter) default: