Skip to content

Commit

Permalink
internal/ethapi: return error when requesting invalid trie key (ether…
Browse files Browse the repository at this point in the history
…eum#25762)

This change makes eth_getProof and eth_getStorageAt return an error when
the argument contains invalid hex in storage keys.

Co-authored-by: Felix Lange <[email protected]>
  • Loading branch information
2 people authored and blakehhuynh committed Oct 3, 2022
1 parent fed352d commit 71cda4f
Showing 1 changed file with 31 additions and 6 deletions.
37 changes: 31 additions & 6 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package ethapi

import (
"context"
"encoding/hex"
"errors"
"fmt"
"math/big"
Expand Down Expand Up @@ -674,15 +675,19 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
}

// create the proof for the storageKeys
for i, key := range storageKeys {
for i, hexKey := range storageKeys {
key, err := decodeHash(hexKey)
if err != nil {
return nil, err
}
if storageTrie != nil {
proof, storageError := state.GetStorageProof(address, common.HexToHash(key))
proof, storageError := state.GetStorageProof(address, key)
if storageError != nil {
return nil, storageError
}
storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(address, common.HexToHash(key)).Big()), toHexSlice(proof)}
storageProof[i] = StorageResult{hexKey, (*hexutil.Big)(state.GetState(address, key).Big()), toHexSlice(proof)}
} else {
storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}}
storageProof[i] = StorageResult{hexKey, &hexutil.Big{}, []string{}}
}
}

Expand All @@ -703,6 +708,22 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
}, state.Error()
}

// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
// be prefixed by 0x and can have an byte length up to 32.
func decodeHash(s string) (common.Hash, error) {
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
s = s[2:]
}
b, err := hex.DecodeString(s)
if err != nil {
return common.Hash{}, fmt.Errorf("hex string invalid")
}
if len(b) > 32 {
return common.Hash{}, fmt.Errorf("hex string too long, want at most 32 bytes")
}
return common.BytesToHash(b), nil
}

// GetHeaderByNumber returns the requested canonical block header.
// * When blockNr is -1 the chain head is returned.
// * When blockNr is -2 the pending chain head is returned.
Expand Down Expand Up @@ -821,12 +842,16 @@ func (s *BlockChainAPI) GetCode(ctx context.Context, address common.Address, blo
// GetStorageAt returns the storage from the state at the given address, key and
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// numbers are also allowed.
func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, hexKey string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
res := state.GetState(address, common.HexToHash(key))
key, err := decodeHash(hexKey)
if err != nil {
return nil, fmt.Errorf("unable to decode storage key: %s", err)
}
res := state.GetState(address, key)
return res[:], state.Error()
}

Expand Down

0 comments on commit 71cda4f

Please sign in to comment.