core/vm: add read only protection for opcodes #33637 (#1984)

This commit is contained in:
Daniel Liu 2026-02-05 15:27:40 +08:00 committed by GitHub
parent 798b0cdf2f
commit 1655f801d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 15 additions and 1 deletions

View file

@ -526,6 +526,9 @@ func opSload(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
}
func opSstore(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
if evm.readOnly {
return nil, ErrWriteProtection
}
loc := scope.Stack.pop()
val := scope.Stack.pop()
evm.StateDB.SetState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32())
@ -757,6 +760,9 @@ func opCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
// Get the arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
if evm.readOnly && !value.IsZero() {
return nil, ErrWriteProtection
}
var bigVal = big0
// TODO(daniel): use uint256.Int instead of converting with toBig()
// By using big0 here, we save an alloc for the most common case (non-ether-transferring contract calls),
@ -901,6 +907,9 @@ func opStop(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
}
func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
if evm.readOnly {
return nil, ErrWriteProtection
}
beneficiary := scope.Stack.pop()
balance := evm.StateDB.GetBalance(scope.Contract.Address())
evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
@ -917,6 +926,9 @@ func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
}
func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
if evm.readOnly {
return nil, ErrWriteProtection
}
beneficiary := scope.Stack.pop()
balance := evm.StateDB.GetBalance(scope.Contract.Address())
evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct)

View file

@ -244,8 +244,10 @@ func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
evm.StateDB.AddAddressToAccessList(address)
gas = params.ColdAccountAccessCostEIP2929
// Terminate the gas measurement if the leftover gas is not sufficient,
// it can effectively prevent accessing the states in the following steps
if contract.Gas < gas {
return gas, nil
return 0, ErrOutOfGas
}
}
// if empty and transfers value