From e70a2b449160d651a898e46288d4e30cbcd3c737 Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Sat, 19 Mar 2016 01:24:23 +0100 Subject: [PATCH] core/vm: fix possible jump table race --- core/vm/jump_table.go | 23 ++++++++++++----------- core/vm/jump_table_test.go | 19 ++++--------------- core/vm/vm.go | 16 +++++++++++----- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 37d7bb160f..8a0f0a01c2 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -1,10 +1,6 @@ package vm -import ( - "math/big" - - "github.com/ethereum/go-ethereum/params" -) +import "math/big" type jumpPtr struct { fn instrFn @@ -13,19 +9,22 @@ type jumpPtr struct { type vmJumpTable [256]jumpPtr -func (jt vmJumpTable) init(blockNumber *big.Int) { +var ( + homesteadJumpTable = newJumpTable(true) + frontierJumpTable = newJumpTable(false) +) + +func newJumpTable(homestead bool) vmJumpTable { + var jumpTable vmJumpTable + // when initialising a new VM execution we must first check the homestead // changes. - if params.IsHomestead(blockNumber) { + if homestead { jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true} } else { jumpTable[DELEGATECALL] = jumpPtr{nil, false} } -} -var jumpTable vmJumpTable - -func init() { jumpTable[ADD] = jumpPtr{opAdd, true} jumpTable[SUB] = jumpPtr{opSub, true} jumpTable[MUL] = jumpPtr{opMul, true} @@ -156,4 +155,6 @@ func init() { jumpTable[JUMP] = jumpPtr{nil, true} jumpTable[JUMPI] = jumpPtr{nil, true} jumpTable[STOP] = jumpPtr{nil, true} + + return jumpTable } diff --git a/core/vm/jump_table_test.go b/core/vm/jump_table_test.go index 98d34bef20..71ffc25116 100644 --- a/core/vm/jump_table_test.go +++ b/core/vm/jump_table_test.go @@ -1,24 +1,13 @@ package vm -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/params" -) +import "testing" func TestInit(t *testing.T) { - params.HomesteadBlock = big.NewInt(1) - - jumpTable.init(big.NewInt(0)) - if jumpTable[DELEGATECALL].valid { + if frontierJumpTable[DELEGATECALL].valid { t.Error("Expected DELEGATECALL not to be present") } - for _, n := range []int64{1, 2, 100} { - jumpTable.init(big.NewInt(n)) - if !jumpTable[DELEGATECALL].valid { - t.Error("Expected DELEGATECALL to be present for block", n) - } + if !homesteadJumpTable[DELEGATECALL].valid { + t.Error("Expected DELEGATECALL not to be present") } } diff --git a/core/vm/vm.go b/core/vm/vm.go index 4b502e3d81..8eb355f86a 100644 --- a/core/vm/vm.go +++ b/core/vm/vm.go @@ -30,15 +30,21 @@ import ( // Vm is an EVM and implements VirtualMachine type Vm struct { - env Environment + env Environment + jumpTable vmJumpTable } // New returns a new Vm func New(env Environment) *Vm { - // init the jump table. Also prepares the homestead changes - jumpTable.init(env.BlockNumber()) + evm := &Vm{env: env} - return &Vm{env: env} + if params.IsHomestead(env.BlockNumber()) { + evm.jumpTable = homesteadJumpTable + } else { + evm.jumpTable = frontierJumpTable + } + + return evm } // Run loops and evaluates the contract's code with the given input data @@ -169,7 +175,7 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) { mem.Resize(newMemSize.Uint64()) // Add a log message self.log(pc, op, contract.Gas, cost, mem, stack, contract, nil) - if opPtr := jumpTable[op]; opPtr.valid { + if opPtr := self.jumpTable[op]; opPtr.valid { if opPtr.fn != nil { opPtr.fn(instruction{}, &pc, self.env, contract, mem, stack) } else {