From 3d62db4f34a5c5e84b4d373f49df3a566b316aec Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 16 Jul 2020 11:47:42 +0300 Subject: [PATCH 1/2] vm: clear altstack on CALL, fix #1158 neo-vm doesn't copy altstack on CALL, so it effectively is cleared. But we need to copy things back on return if there are any. --- pkg/vm/vm.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 0312f01a6..3276ae567 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -258,8 +258,9 @@ func (v *VM) Load(prog []byte) { func (v *VM) LoadScript(b []byte) { ctx := NewContext(b) ctx.estack = v.estack - ctx.astack = v.astack + ctx.astack = v.newItemStack("alt") v.istack.PushVal(ctx) + v.astack = ctx.astack } // loadScriptWithHash if similar to the LoadScript method, but it also loads @@ -1138,6 +1139,8 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro newCtx := ctx.Copy() newCtx.rvcount = -1 + newCtx.astack = v.newItemStack("alt") + v.astack = newCtx.astack v.istack.PushVal(newCtx) offset := v.getJumpOffset(newCtx, parameter, 0) @@ -1202,8 +1205,15 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro newEstack.Push(elem) } v.estack = newEstack - v.astack = v.Context().astack } + newAstack := v.Context().astack + if rvcount == -1 && newAstack != oldCtx.astack { + for i := oldCtx.astack.Len(); i > 0; i-- { + elem := oldCtx.astack.RemoveAt(i - 1) + newAstack.Push(elem) + } + } + v.astack = newAstack case opcode.CHECKSIG, opcode.VERIFY: var hashToCheck []byte From 35c60cd8f48f8b06ec833ebf72e27b86b1485ec2 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 16 Jul 2020 17:14:27 +0300 Subject: [PATCH 2/2] vm: fix elements counting for isolated calls The map and the counter are VM-wide, not context-specific, that's the whole point of them. --- pkg/vm/vm.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 3276ae567..5ef50aa51 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -1391,8 +1391,8 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro newCtx.hasDynamicInvoke = hasDynamicInvoke } newCtx.rvcount = rvcount - newCtx.estack = NewStack("evaluation") - newCtx.astack = NewStack("alt") + newCtx.estack = v.newItemStack("evaluation") + newCtx.astack = v.newItemStack("alt") // Going backwards to naturally push things onto the new stack. for i := pcount; i > 0; i-- { elem := v.estack.RemoveAt(i - 1)