From 82fa4de0e79cfa3a51658d77f55b5e2bdfe62349 Mon Sep 17 00:00:00 2001 From: jochem-brouwer Date: Thu, 30 Apr 2020 19:45:00 +0200 Subject: [PATCH] vm: explicitly duplicate bignumbers on stack (#733) * explicitly duplicate bignumbers on stack * vm: add test to check for internally editing stack items Co-authored-by: Ev --- lib/evm/stack.ts | 2 +- tests/api/evm/stack.js | 48 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/evm/stack.ts b/lib/evm/stack.ts index 156b243335..f997027d26 100644 --- a/lib/evm/stack.ts +++ b/lib/evm/stack.ts @@ -85,6 +85,6 @@ export default class Stack { } const i = this._store.length - position - this.push(this._store[i]) + this.push(this._store[i].clone()) } } diff --git a/tests/api/evm/stack.js b/tests/api/evm/stack.js index 6a1b24adaf..ad9240f9ff 100644 --- a/tests/api/evm/stack.js +++ b/tests/api/evm/stack.js @@ -1,6 +1,8 @@ const tape = require('tape') const BN = require('bn.js') const Stack = require('../../../dist/evm/stack').default +const VM = require('../../../dist/index').default +const { createAccount } = require('../utils') tape('Stack', t => { t.test('should be empty initially', st => { @@ -111,4 +113,50 @@ tape('Stack', t => { st.throws(() => s.push(max.addn(1))) st.end() }) + + t.test('stack items should not change if they are DUPed', async st => { + const caller = Buffer.from('00000000000000000000000000000000000000ee', 'hex') + const addr = Buffer.from('00000000000000000000000000000000000000ff', 'hex') + const key = new BN(0).toArrayLike(Buffer, 'be', 32) + const vm = new VM() + const account = createAccount('0x00', '0x00') + const code = "60008080808060013382F15060005260206000F3" + const expectedReturnValue = new BN(0).toArrayLike(Buffer, 'be', 32) + /* + code: remarks: (top of the stack is at the zero index) + PUSH1 0x00 + DUP1 + DUP1 + DUP1 + DUP1 + PUSH1 0x01 + CALLER + DUP3 + CALL stack: [0, CALLER, 1, 0, 0, 0, 0, 0] + POP pop the call result (1) + PUSH1 0x00 + MSTORE we now expect that the stack (prior to MSTORE) is [0, 0] + PUSH1 0x20 + PUSH1 0x00 + RETURN stack: [0, 0x20] (we thus return the stack item which was originally pushed as 0, and then DUPed) + */ + await vm.stateManager.putAccount(addr, account) + await vm.stateManager.putContractCode(addr, Buffer.from(code, 'hex')) + const runCallArgs = { + caller: caller, + gasLimit: new BN(0xffffffffff), + to: addr, + value: new BN(1) + } + try { + const res = await vm.runCall(runCallArgs) + const executionReturnValue = res.execResult.returnValue + st.assert(executionReturnValue.equals(expectedReturnValue)) + st.end() + } catch(e) { + st.fail(e.message) + } + }) + + })