Skip to content

Commit ac92d7c

Browse files
authored
Merge pull request #14570 from Arachnid/jumpdestanalysis
core/vm: Use a bitmap instead of a map for jumpdest analysis
2 parents 0424192 + d5a7993 commit ac92d7c

File tree

1 file changed

+12
-14
lines changed

1 file changed

+12
-14
lines changed

core/vm/analysis.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,39 @@ import (
2222
"github.com/ethereum/go-ethereum/common"
2323
)
2424

25-
var bigMaxUint64 = new(big.Int).SetUint64(^uint64(0))
26-
2725
// destinations stores one map per contract (keyed by hash of code).
2826
// The maps contain an entry for each location of a JUMPDEST
2927
// instruction.
30-
type destinations map[common.Hash]map[uint64]struct{}
28+
type destinations map[common.Hash][]byte
3129

3230
// has checks whether code has a JUMPDEST at dest.
3331
func (d destinations) has(codehash common.Hash, code []byte, dest *big.Int) bool {
34-
// PC cannot go beyond len(code) and certainly can't be bigger than 64bits.
32+
// PC cannot go beyond len(code) and certainly can't be bigger than 63bits.
3533
// Don't bother checking for JUMPDEST in that case.
36-
if dest.Cmp(bigMaxUint64) > 0 {
34+
udest := dest.Uint64()
35+
if dest.BitLen() >= 63 || udest >= uint64(len(code)) {
3736
return false
3837
}
38+
3939
m, analysed := d[codehash]
4040
if !analysed {
4141
m = jumpdests(code)
4242
d[codehash] = m
4343
}
44-
_, ok := m[dest.Uint64()]
45-
return ok
44+
return (m[udest/8] & (1 << (udest % 8))) != 0
4645
}
4746

4847
// jumpdests creates a map that contains an entry for each
4948
// PC location that is a JUMPDEST instruction.
50-
func jumpdests(code []byte) map[uint64]struct{} {
51-
m := make(map[uint64]struct{})
49+
func jumpdests(code []byte) []byte {
50+
m := make([]byte, len(code)/8+1)
5251
for pc := uint64(0); pc < uint64(len(code)); pc++ {
53-
var op OpCode = OpCode(code[pc])
54-
switch op {
55-
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
52+
op := OpCode(code[pc])
53+
if op == JUMPDEST {
54+
m[pc/8] |= 1 << (pc % 8)
55+
} else if op >= PUSH1 && op <= PUSH32 {
5656
a := uint64(op) - uint64(PUSH1) + 1
5757
pc += a
58-
case JUMPDEST:
59-
m[pc] = struct{}{}
6058
}
6159
}
6260
return m

0 commit comments

Comments
 (0)