mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
core/vm: fix possible jump table race
This commit is contained in:
parent
34b622a248
commit
e70a2b4491
3 changed files with 27 additions and 31 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue