From 466af55deaed71a91aef4a2a5e874fde85fd1216 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 24 Jul 2020 13:09:02 +0300 Subject: [PATCH] vm: isolate stack in LoadScript When calling contract it must be provided with a new stack containing only it's arguments. The result is then copied back on RET. Fix #1220. --- pkg/core/interop_system_test.go | 16 ++++++++++++++++ pkg/vm/vm.go | 1 + 2 files changed, 17 insertions(+) diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 941e51529..d3b33add2 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -329,6 +329,7 @@ func getTestContractState() *state.Contract { byte(opcode.ABORT), // abort if no offset was provided byte(opcode.ADD), byte(opcode.RET), byte(opcode.PUSH7), byte(opcode.RET), + byte(opcode.DROP), byte(opcode.RET), } h := hash.Hash160(script) m := manifest.NewManifest(h) @@ -348,6 +349,11 @@ func getTestContractState() *state.Contract { Parameters: []manifest.Parameter{}, ReturnType: smartcontract.IntegerType, }, + { + Name: "drop", + Offset: 5, + ReturnType: smartcontract.VoidType, + }, } return &state.Contract{ Script: script, @@ -375,6 +381,7 @@ func TestContractCall(t *testing.T) { m := manifest.NewManifest(hash.Hash160(currScript)) perm := manifest.NewPermission(manifest.PermissionHash, h) perm.Methods.Add("add") + perm.Methods.Add("drop") m.Permissions = append(m.Permissions, *perm) require.NoError(t, ic.DAO.PutContractState(&state.Contract{ @@ -425,6 +432,15 @@ func TestContractCall(t *testing.T) { t.Run("NotEnoughArguments", runInvalid( stackitem.NewArray([]stackitem.Item{stackitem.Make(1)}), "add", h.BytesBE())) }) + + t.Run("IsolatedStack", func(t *testing.T) { + initVM(v) + v.Estack().PushVal(stackitem.NewArray(nil)) + v.Estack().PushVal("drop") + v.Estack().PushVal(h.BytesBE()) + require.NoError(t, contractCall(ic, v)) + require.Error(t, v.Run()) + }) } func TestContractCreate(t *testing.T) { diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 78961146f..d9e294731 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -279,6 +279,7 @@ func (v *VM) LoadScript(b []byte) { // LoadScriptWithFlags loads script and sets call flag to f. func (v *VM) LoadScriptWithFlags(b []byte, f smartcontract.CallFlag) { ctx := NewContext(b) + v.estack = v.newItemStack("estack") ctx.estack = v.estack ctx.tryStack = NewStack("exception") ctx.callFlag = f