mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/vm: use 64-bit memory calculations
This commit is contained in:
parent
6a4bf5d697
commit
e17df3ebce
4 changed files with 107 additions and 58 deletions
|
|
@ -23,13 +23,47 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common/math"
|
||||
)
|
||||
|
||||
// calculates the memory size required for a step
|
||||
func calcMemSize(off, l *big.Int) *big.Int {
|
||||
// calcMemSize64 calculates the required memory size, and returns
|
||||
// the size and whether the result overflowed uint64
|
||||
func calcMemSize64(off, l *big.Int) (uint64, bool) {
|
||||
// if length is zero, memsize is always zero, regardless of offset
|
||||
if l.Sign() == 0 {
|
||||
return common.Big0
|
||||
return 0, true
|
||||
}
|
||||
// Check that neither offset nor length overflows
|
||||
if off.BitLen() > 64 || l.BitLen() > 64 {
|
||||
return 0, true
|
||||
}
|
||||
|
||||
return new(big.Int).Add(off, l)
|
||||
offset64 := off.Uint64()
|
||||
length64 := l.Uint64()
|
||||
val := offset64 + length64
|
||||
// Check that the total doesn't overflow
|
||||
if val < offset64 {
|
||||
return 0, true
|
||||
}
|
||||
return val, false
|
||||
}
|
||||
|
||||
// calcMemSize64WithUint calculates the required memory size, and returns
|
||||
// the size and whether the result overflowed uint64
|
||||
// Identical to calcMemSize64, but length is a uint64
|
||||
func calcMemSize64WithUint(off *big.Int, length64 uint64) (uint64, bool) {
|
||||
// if length is zero, memsize is always zero, regardless of offset
|
||||
if length64 == 0 {
|
||||
return 0, true
|
||||
}
|
||||
// Check that offset doesn't overflow
|
||||
if off.BitLen() > 64 {
|
||||
return 0, true
|
||||
}
|
||||
offset64 := off.Uint64()
|
||||
val := offset64 + length64
|
||||
// Check that the total doesn't overflow
|
||||
if val < offset64 {
|
||||
return 0, true
|
||||
}
|
||||
return val, false
|
||||
}
|
||||
|
||||
// getData returns a slice from the data based on the start and size and pads
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
// calculate the new memory size and expand the memory to fit
|
||||
// the operation
|
||||
if operation.memorySize != nil {
|
||||
memSize, overflow := bigUint64(operation.memorySize(stack))
|
||||
memSize, overflow := operation.memorySize(stack)
|
||||
if overflow {
|
||||
return nil, errGasUintOverflow
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package vm
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
|
@ -26,8 +25,8 @@ import (
|
|||
type (
|
||||
executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
|
||||
gasFunc func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
|
||||
//stackValidationFunc func(*Stack) error
|
||||
memorySizeFunc func(*Stack) *big.Int
|
||||
// memorySizeFunc returns the required size, and whether the operation overflowed a uint64
|
||||
memorySizeFunc func(*Stack) (size uint64, overflow bool)
|
||||
)
|
||||
|
||||
var errGasUintOverflow = errors.New("gas uint64 overflow")
|
||||
|
|
|
|||
|
|
@ -16,82 +16,98 @@
|
|||
|
||||
package vm
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
)
|
||||
|
||||
func memorySha3(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(1))
|
||||
func memorySha3(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(0), stack.Back(1))
|
||||
}
|
||||
|
||||
func memoryCallDataCopy(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||
func memoryCallDataCopy(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(0), stack.Back(2))
|
||||
}
|
||||
|
||||
func memoryReturnDataCopy(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||
func memoryReturnDataCopy(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(0), stack.Back(2))
|
||||
}
|
||||
|
||||
func memoryCodeCopy(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(2))
|
||||
func memoryCodeCopy(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(0), stack.Back(2))
|
||||
}
|
||||
|
||||
func memoryExtCodeCopy(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(1), stack.Back(3))
|
||||
func memoryExtCodeCopy(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(1), stack.Back(3))
|
||||
}
|
||||
|
||||
func memoryMLoad(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), big.NewInt(32))
|
||||
func memoryMLoad(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64WithUint(stack.Back(0), 32)
|
||||
}
|
||||
|
||||
func memoryMStore8(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), big.NewInt(1))
|
||||
func memoryMStore8(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64WithUint(stack.Back(0), 1)
|
||||
}
|
||||
|
||||
func memoryMStore(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), big.NewInt(32))
|
||||
func memoryMStore(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64WithUint(stack.Back(0), 32)
|
||||
}
|
||||
|
||||
func memoryCreate(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(1), stack.Back(2))
|
||||
func memoryCreate(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(1), stack.Back(2))
|
||||
}
|
||||
|
||||
func memoryCreate2(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(1), stack.Back(2))
|
||||
func memoryCreate2(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(1), stack.Back(2))
|
||||
}
|
||||
|
||||
func memoryCall(stack *Stack) *big.Int {
|
||||
x := calcMemSize(stack.Back(5), stack.Back(6))
|
||||
y := calcMemSize(stack.Back(3), stack.Back(4))
|
||||
|
||||
return math.BigMax(x, y)
|
||||
func memoryCall(stack *Stack) (uint64, bool) {
|
||||
x, overflow := calcMemSize64(stack.Back(5), stack.Back(6))
|
||||
if overflow {
|
||||
return 0, true
|
||||
}
|
||||
y, overflow := calcMemSize64(stack.Back(3), stack.Back(4))
|
||||
if overflow {
|
||||
return 0, true
|
||||
}
|
||||
if x > y {
|
||||
return x, false
|
||||
}
|
||||
return y, false
|
||||
}
|
||||
func memoryDelegateCall(stack *Stack) (uint64, bool) {
|
||||
x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
|
||||
if overflow {
|
||||
return 0, true
|
||||
}
|
||||
y, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
|
||||
if overflow {
|
||||
return 0, true
|
||||
}
|
||||
if x > y {
|
||||
return x, false
|
||||
}
|
||||
return y, false
|
||||
}
|
||||
|
||||
func memoryDelegateCall(stack *Stack) *big.Int {
|
||||
x := calcMemSize(stack.Back(4), stack.Back(5))
|
||||
y := calcMemSize(stack.Back(2), stack.Back(3))
|
||||
|
||||
return math.BigMax(x, y)
|
||||
func memoryStaticCall(stack *Stack) (uint64, bool) {
|
||||
x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
|
||||
if overflow {
|
||||
return 0, true
|
||||
}
|
||||
y, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
|
||||
if overflow {
|
||||
return 0, true
|
||||
}
|
||||
if x > y {
|
||||
return x, false
|
||||
}
|
||||
return y, false
|
||||
}
|
||||
|
||||
func memoryStaticCall(stack *Stack) *big.Int {
|
||||
x := calcMemSize(stack.Back(4), stack.Back(5))
|
||||
y := calcMemSize(stack.Back(2), stack.Back(3))
|
||||
|
||||
return math.BigMax(x, y)
|
||||
func memoryReturn(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(0), stack.Back(1))
|
||||
}
|
||||
|
||||
func memoryReturn(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(1))
|
||||
func memoryRevert(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(0), stack.Back(1))
|
||||
}
|
||||
|
||||
func memoryRevert(stack *Stack) *big.Int {
|
||||
return calcMemSize(stack.Back(0), stack.Back(1))
|
||||
}
|
||||
|
||||
func memoryLog(stack *Stack) *big.Int {
|
||||
mSize, mStart := stack.Back(1), stack.Back(0)
|
||||
return calcMemSize(mStart, mSize)
|
||||
func memoryLog(stack *Stack) (uint64, bool) {
|
||||
return calcMemSize64(stack.Back(0), stack.Back(1))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue