core/vm: fix possible jump table race

This commit is contained in:
Jeffrey Wilcke 2016-03-19 01:24:23 +01:00
parent 34b622a248
commit e70a2b4491
3 changed files with 27 additions and 31 deletions

View file

@ -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
}

View file

@ -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")
}
}

View file

@ -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 {