From 13b9eda08dff6cac445fac42ec660e89290f82d6 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 24 Jul 2020 11:56:35 +0300 Subject: [PATCH] vm: allow to call VM methods from outside Abstract out (*VM).Call method and use in in CALL* opcodes. --- pkg/vm/vm.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 558d8ccc4..78961146f 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -1235,13 +1235,9 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro case opcode.CALL, opcode.CALLL: v.checkInvocationStackSize() - newCtx := ctx.Copy() - newCtx.local = nil - newCtx.arguments = nil - v.istack.PushVal(newCtx) - - offset := v.getJumpOffset(newCtx, parameter) - v.Jump(newCtx, offset) + // Note: jump offset must be calculated regarding to new context, + // but it is cloned and thus has the same script and instruction pointer. + v.Call(ctx, v.getJumpOffset(ctx, parameter)) case opcode.CALLA: ptr := v.estack.Pop().Item().(*stackitem.Pointer) @@ -1249,11 +1245,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic("invalid script in pointer") } - newCtx := ctx.Copy() - newCtx.local = nil - newCtx.arguments = nil - v.istack.PushVal(newCtx) - v.Jump(newCtx, ptr.Position()) + v.Call(ctx, ptr.Position()) case opcode.SYSCALL: interopID := GetInteropID(parameter) @@ -1471,6 +1463,16 @@ func (v *VM) Jump(ctx *Context, offset int) { ctx.nextip = offset } +// Call calls method by offset. It is similar to Jump but also +// pushes new context to the invocation state +func (v *VM) Call(ctx *Context, offset int) { + newCtx := ctx.Copy() + newCtx.local = nil + newCtx.arguments = nil + v.istack.PushVal(newCtx) + v.Jump(newCtx, offset) +} + // getJumpOffset returns instruction number in a current context // to a which JMP should be performed. // parameter should have length either 1 or 4 and