mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
core/vm: fix opReturnDataLoad
This commit is contained in:
parent
fa6b1b9fa1
commit
a1b359f310
6 changed files with 77 additions and 9 deletions
|
|
@ -725,10 +725,10 @@ func enableEOF(jt *JumpTable) {
|
||||||
jt[EXTCALL] = &operation{
|
jt[EXTCALL] = &operation{
|
||||||
execute: opExtCall,
|
execute: opExtCall,
|
||||||
constantGas: params.CallGasEIP150,
|
constantGas: params.CallGasEIP150,
|
||||||
dynamicGas: gasCall,
|
dynamicGas: gasCallExt,
|
||||||
minStack: minStack(4, 1),
|
minStack: minStack(4, 1),
|
||||||
maxStack: maxStack(4, 1),
|
maxStack: maxStack(4, 1),
|
||||||
memorySize: memoryCall,
|
memorySize: memoryExtCall,
|
||||||
}
|
}
|
||||||
jt[EXTDELEGATECALL] = &operation{
|
jt[EXTDELEGATECALL] = &operation{
|
||||||
execute: opExtDelegateCall,
|
execute: opExtDelegateCall,
|
||||||
|
|
@ -1073,17 +1073,18 @@ func opReturnDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
||||||
var (
|
var (
|
||||||
offset = scope.Stack.pop()
|
offset = scope.Stack.pop()
|
||||||
)
|
)
|
||||||
if offset.Uint64()+32 > uint64(len(interpreter.returnData)) {
|
offset64, overflow := offset.Uint64WithOverflow()
|
||||||
return nil, errors.New("return buffer overflow")
|
if overflow {
|
||||||
|
offset64 = math.MaxUint64
|
||||||
}
|
}
|
||||||
scope.Stack.push(offset.SetBytes(interpreter.returnData[offset.Uint64() : offset.Uint64()+32]))
|
scope.Stack.push(offset.SetBytes(getData(interpreter.returnData, offset64, 32)))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opExtCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func opExtCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
stack := scope.Stack
|
stack := scope.Stack
|
||||||
// Use all available gas
|
// Use all available gas
|
||||||
gas := (scope.Contract.Gas / 64) * 63
|
gas := interpreter.evm.callGasTemp
|
||||||
// Pop other call parameters.
|
// Pop other call parameters.
|
||||||
addr, value, inOffset, inSize := stack.pop(), stack.pop(), stack.pop(), stack.pop()
|
addr, value, inOffset, inSize := stack.pop(), stack.pop(), stack.pop(), stack.pop()
|
||||||
toAddr := common.Address(addr.Bytes20())
|
toAddr := common.Address(addr.Bytes20())
|
||||||
|
|
@ -1106,7 +1107,7 @@ func opExtCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
|
||||||
temp.SetOne()
|
temp.SetOne()
|
||||||
}
|
}
|
||||||
stack.push(&temp)
|
stack.push(&temp)
|
||||||
|
fmt.Println(returnGas)
|
||||||
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||||
|
|
||||||
interpreter.returnData = ret
|
interpreter.returnData = ret
|
||||||
|
|
|
||||||
|
|
@ -689,7 +689,7 @@ func (evm *EVM) GetVMContext() *tracing.VMContext {
|
||||||
|
|
||||||
// parseContainer tries to parse an EOF container if the Shanghai fork is active. It expects the code to already be validated.
|
// parseContainer tries to parse an EOF container if the Shanghai fork is active. It expects the code to already be validated.
|
||||||
func (evm *EVM) parseContainer(b []byte) *Container {
|
func (evm *EVM) parseContainer(b []byte) *Container {
|
||||||
if evm.chainRules.IsShanghai {
|
if evm.chainRules.IsPrague {
|
||||||
var c Container
|
var c Container
|
||||||
if err := c.UnmarshalBinary(b); err != nil && strings.HasPrefix(err.Error(), "invalid magic") {
|
if err := c.UnmarshalBinary(b); err != nil && strings.HasPrefix(err.Error(), "invalid magic") {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ func callGas(isEip150 bool, availableGas, base uint64, callCost *uint256.Int) (u
|
||||||
// If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150
|
// If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150
|
||||||
// is smaller than the requested amount. Therefore we return the new gas instead
|
// is smaller than the requested amount. Therefore we return the new gas instead
|
||||||
// of returning an error.
|
// of returning an error.
|
||||||
if !callCost.IsUint64() || gas < callCost.Uint64() {
|
if !callCost.IsUint64() || gas <= callCost.Uint64() {
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
// memoryGasCost calculates the quadratic gas for memory expansion. It does so
|
// memoryGasCost calculates the quadratic gas for memory expansion. It does so
|
||||||
|
|
@ -413,6 +414,51 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gasCallExt(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
var (
|
||||||
|
gas uint64
|
||||||
|
transfersValue = !stack.Back(2).IsZero()
|
||||||
|
address = common.Address(stack.Back(1).Bytes20())
|
||||||
|
)
|
||||||
|
if evm.chainRules.IsEIP158 {
|
||||||
|
if transfersValue && evm.StateDB.Empty(address) {
|
||||||
|
gas += params.CallNewAccountGas
|
||||||
|
}
|
||||||
|
} else if !evm.StateDB.Exist(address) {
|
||||||
|
gas += params.CallNewAccountGas
|
||||||
|
}
|
||||||
|
if transfersValue && !evm.chainRules.IsEIP4762 {
|
||||||
|
gas += params.CallValueTransferGas
|
||||||
|
}
|
||||||
|
memoryGas, err := memoryGasCost(mem, memorySize)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var overflow bool
|
||||||
|
if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
|
||||||
|
return 0, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
if evm.chainRules.IsEIP4762 {
|
||||||
|
if transfersValue {
|
||||||
|
gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address))
|
||||||
|
if overflow {
|
||||||
|
return 0, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evm.callGasTemp, err = callGas(true, contract.Gas, gas, new(uint256.Int).SetUint64(contract.Gas))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
|
||||||
|
return 0, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
|
||||||
|
return gas, nil
|
||||||
|
}
|
||||||
|
|
||||||
func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
memoryGas, err := memoryGasCost(mem, memorySize)
|
memoryGas, err := memoryGasCost(mem, memorySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,18 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
|
||||||
length = scope.Stack.pop()
|
length = scope.Stack.pop()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if scope.Contract.IsEOF() {
|
||||||
|
dataOffset64, overflow := dataOffset.Uint64WithOverflow()
|
||||||
|
if overflow {
|
||||||
|
dataOffset64 = math.MaxUint64
|
||||||
|
}
|
||||||
|
// These values are checked for overflow during gas cost calculation
|
||||||
|
memOffset64 := memOffset.Uint64()
|
||||||
|
length64 := length.Uint64()
|
||||||
|
scope.Memory.Set(memOffset64, length64, getData(interpreter.returnData, dataOffset64, length64))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
offset64, overflow := dataOffset.Uint64WithOverflow()
|
offset64, overflow := dataOffset.Uint64WithOverflow()
|
||||||
if overflow {
|
if overflow {
|
||||||
return nil, ErrReturnDataOutOfBounds
|
return nil, ErrReturnDataOutOfBounds
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ func memoryCall(stack *Stack) (uint64, bool) {
|
||||||
}
|
}
|
||||||
return y, false
|
return y, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func memoryDelegateCall(stack *Stack) (uint64, bool) {
|
func memoryDelegateCall(stack *Stack) (uint64, bool) {
|
||||||
x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
|
x, overflow := calcMemSize64(stack.Back(4), stack.Back(5))
|
||||||
if overflow {
|
if overflow {
|
||||||
|
|
@ -116,6 +117,14 @@ func memoryStaticCall(stack *Stack) (uint64, bool) {
|
||||||
return y, false
|
return y, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func memoryExtCall(stack *Stack) (uint64, bool) {
|
||||||
|
x, overflow := calcMemSize64(stack.Back(2), stack.Back(3))
|
||||||
|
if overflow {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
return x, false
|
||||||
|
}
|
||||||
|
|
||||||
func memoryReturn(stack *Stack) (uint64, bool) {
|
func memoryReturn(stack *Stack) (uint64, bool) {
|
||||||
return calcMemSize64(stack.Back(0), stack.Back(1))
|
return calcMemSize64(stack.Back(0), stack.Back(1))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue