aboutsummaryrefslogtreecommitdiff
path: root/core/vm/contract.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/contract.go')
-rw-r--r--core/vm/contract.go36
1 files changed, 32 insertions, 4 deletions
diff --git a/core/vm/contract.go b/core/vm/contract.go
index ed17402..915193d 100644
--- a/core/vm/contract.go
+++ b/core/vm/contract.go
@@ -19,7 +19,8 @@ package vm
import (
"math/big"
- "github.com/ava-labs/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/holiman/uint256"
)
// ContractRef is a reference to the contract's backing object
@@ -81,18 +82,43 @@ func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uin
return c
}
-func (c *Contract) validJumpdest(dest *big.Int) bool {
- udest := dest.Uint64()
+func (c *Contract) validJumpdest(dest *uint256.Int) bool {
+ udest, overflow := dest.Uint64WithOverflow()
// PC cannot go beyond len(code) and certainly can't be bigger than 63bits.
// Don't bother checking for JUMPDEST in that case.
- if dest.BitLen() >= 63 || udest >= uint64(len(c.Code)) {
+ if overflow || udest >= uint64(len(c.Code)) {
return false
}
// Only JUMPDESTs allowed for destinations
if OpCode(c.Code[udest]) != JUMPDEST {
return false
}
+ return c.isCode(udest)
+}
+
+func (c *Contract) validJumpSubdest(udest uint64) bool {
+ // PC cannot go beyond len(code) and certainly can't be bigger than 63 bits.
+ // Don't bother checking for BEGINSUB in that case.
+ if int64(udest) < 0 || udest >= uint64(len(c.Code)) {
+ return false
+ }
+ // Only BEGINSUBs allowed for destinations
+ if OpCode(c.Code[udest]) != BEGINSUB {
+ return false
+ }
+ return c.isCode(udest)
+}
+
+// isCode returns true if the provided PC location is an actual opcode, as
+// opposed to a data-segment following a PUSHN operation.
+func (c *Contract) isCode(udest uint64) bool {
+ // Do we already have an analysis laying around?
+ if c.analysis != nil {
+ return c.analysis.codeSegment(udest)
+ }
// Do we have a contract hash already?
+ // If we do have a hash, that means it's a 'regular' contract. For regular
+ // contracts ( not temporary initcode), we store the analysis in a map
if c.CodeHash != (common.Hash{}) {
// Does parent context have the analysis?
analysis, exist := c.jumpdests[c.CodeHash]
@@ -102,6 +128,8 @@ func (c *Contract) validJumpdest(dest *big.Int) bool {
analysis = codeBitmap(c.Code)
c.jumpdests[c.CodeHash] = analysis
}
+ // Also stash it in current contract for faster access
+ c.analysis = analysis
return analysis.codeSegment(udest)
}
// We don't have the code hash, most likely a piece of initcode not already