Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
}
var extraEips []int
for _, eip := range cfg.ExtraEips {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

		if len(cfg.ExtraEips) > 0 {
			// Deep-copy jumptable to prevent modification of opcodes in other tables
			cfg.JumpTable := copyJumpTable(cfg.JumpTable)
		}
		for _, eip := range cfg.ExtraEips {
			if err := EnableEIP(eip, &cfg.JumpTable); err != nil {
				// Disable it, so caller can check if it's activated or not
				log.Error("EIP activation failed", "eip", eip, "error", err)
			} else {
				extraEips = append(extraEips, eip)
			}
		}

Would this work? No need to deep-copy it multiple times

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the original one also prevents a partial write if EnableEIP returns an error in the middle.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, the original one set cfg.JumpTable unconditionally, so it don't prevent a partial write neither.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Doesn't matter a whole lot, this is not a hot path (for us)

Copy link
Author

@yihuang yihuang Nov 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And there's no partial write to prevent anyway, I just changed to your version.

copy := *cfg.JumpTable
if err := EnableEIP(eip, &copy); err != nil {
copy := copyJumpTable(cfg.JumpTable)
if err := EnableEIP(eip, copy); err != nil {
// Disable it, so caller can check if it's activated or not
log.Error("EIP activation failed", "eip", eip, "error", err)
} else {
extraEips = append(extraEips, eip)
}
cfg.JumpTable = &copy
cfg.JumpTable = copy
}
cfg.ExtraEips = extraEips
}
Expand Down
11 changes: 11 additions & 0 deletions core/vm/jump_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -1043,3 +1043,14 @@ func newFrontierInstructionSet() JumpTable {

return validate(tbl)
}

func copyJumpTable(source *JumpTable) *JumpTable {
dest := *source
for i, op := range source {
if op != nil {
opCopy := *op
dest[i] = &opCopy
}
}
return &dest
}
41 changes: 41 additions & 0 deletions core/vm/jump_table_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package vm

import (
"testing"

"github.com/stretchr/testify/require"
)

// TestJumpTableCopy tests that deep copy is necessery to prevent modify shared jump table
func TestJumpTableCopy(t *testing.T) {
tbl := newMergeInstructionSet()
require.Equal(t, uint64(0), tbl[SLOAD].constantGas)

// a deep copy won't modify the shared jump table
deepCopy := copyJumpTable(&tbl)
deepCopy[SLOAD].constantGas = 100
require.Equal(t, uint64(100), deepCopy[SLOAD].constantGas)
require.Equal(t, uint64(0), tbl[SLOAD].constantGas)

// but a shallow copy will modify the shared table
shallowCopy := tbl
shallowCopy[SLOAD].constantGas = 100
require.Equal(t, uint64(100), shallowCopy[SLOAD].constantGas)
require.Equal(t, uint64(100), tbl[SLOAD].constantGas)
}