Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: check store keys length before accessing #9639

Merged
merged 18 commits into from
Jul 8, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Bug Fixes

* [\#9639](https://github.com/cosmos/cosmos-sdk/pull/9639) Check store keys length before accessing them by making sure that `key` is of length `m+1` (for `a := key[n:m]`)
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
* (types) [\#9627](https://github.com/cosmos/cosmos-sdk/pull/9627) Fix nil pointer panic on `NewBigIntFromInt`
* (x/genutil) [\#9574](https://github.com/cosmos/cosmos-sdk/pull/9575) Actually use the `gentx` client tx flags (like `--keyring-dir`)
* (x/distribution) [\#9599](https://github.com/cosmos/cosmos-sdk/pull/9599) Withdraw rewards event now includes a value attribute even if there are 0 rewards (due to situations like 100% commission).
Expand Down
9 changes: 9 additions & 0 deletions types/kv/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package kv

import "fmt"

func AssertKeyAtLeastLength(bz []byte, length int) {
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
if len(bz) < length {
panic(fmt.Sprintf("expected key of length at least %d, got %d", length, len(bz)))
}
}
3 changes: 3 additions & 0 deletions x/authz/keeper/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/cosmos/cosmos-sdk/internal/conv"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/kv"
"github.com/cosmos/cosmos-sdk/x/authz"
)

Expand Down Expand Up @@ -38,8 +39,10 @@ func grantStoreKey(grantee sdk.AccAddress, granter sdk.AccAddress, msgType strin
func addressesFromGrantStoreKey(key []byte) (granterAddr, granteeAddr sdk.AccAddress) {
// key is of format:
// 0x01<granterAddressLen (1 Byte)><granterAddress_Bytes><granteeAddressLen (1 Byte)><granteeAddress_Bytes><msgType_Bytes>
kv.AssertKeyAtLeastLength(key, 2)
granterAddrLen := key[1] // remove prefix key
granterAddr = sdk.AccAddress(key[2 : 2+granterAddrLen])
kv.AssertKeyAtLeastLength(key, int(3+granterAddrLen))
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
granteeAddrLen := int(key[2+granterAddrLen])
granteeAddr = sdk.AccAddress(key[3+granterAddrLen : 3+granterAddrLen+byte(granteeAddrLen)])

Expand Down
2 changes: 2 additions & 0 deletions x/bank/migrations/v040/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/kv"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/migrations/v040"
)

Expand Down Expand Up @@ -40,6 +41,7 @@ func DenomMetadataKey(denom string) []byte {
// store. The key must not contain the perfix BalancesPrefix as the prefix store
// iterator discards the actual prefix.
func AddressFromBalancesStore(key []byte) sdk.AccAddress {
kv.AssertKeyAtLeastLength(key, 1+v040auth.AddrLen)
addr := key[:v040auth.AddrLen]
if len(addr) != v040auth.AddrLen {
panic(fmt.Sprintf("unexpected account address key length; got: %d, expected: %d", len(addr), v040auth.AddrLen))
Expand Down
9 changes: 9 additions & 0 deletions x/distribution/migrations/v040/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/binary"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/kv"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/migrations/v040"
)

Expand Down Expand Up @@ -58,6 +59,7 @@ var (

// gets an address from a validator's outstanding rewards key
func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress) {
kv.AssertKeyAtLeastLength(key, 2)
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
Expand All @@ -67,6 +69,7 @@ func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress)

// gets an address from a delegator's withdraw info key
func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) {
kv.AssertKeyAtLeastLength(key, 2)
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
Expand All @@ -76,6 +79,7 @@ func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) {

// gets the addresses from a delegator starting info key
func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) {
kv.AssertKeyAtLeastLength(key, 2+v040auth.AddrLen)
addr := key[1 : 1+v040auth.AddrLen]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
Expand All @@ -91,6 +95,7 @@ func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delA

// gets the address & period from a validator's historical rewards key
func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) {
kv.AssertKeyAtLeastLength(key, 2+v040auth.AddrLen)
addr := key[1 : 1+v040auth.AddrLen]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
Expand All @@ -106,6 +111,7 @@ func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddr

// gets the address from a validator's current rewards key
func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) {
kv.AssertKeyAtLeastLength(key, 2)
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
Expand All @@ -115,6 +121,7 @@ func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) {

// gets the address from a validator's accumulated commission key
func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) {
kv.AssertKeyAtLeastLength(key, 2)
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
Expand All @@ -124,12 +131,14 @@ func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddres

// gets the height from a validator's slash event key
func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) {
kv.AssertKeyAtLeastLength(key, 2+v040auth.AddrLen)
addr := key[1 : 1+v040auth.AddrLen]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
valAddr = sdk.ValAddress(addr)
startB := 1 + v040auth.AddrLen
kv.AssertKeyAtLeastLength(key, startB+9)
b := key[startB : startB+8] // the next 8 bytes represent the height
height = binary.BigEndian.Uint64(b)
return
Expand Down
12 changes: 12 additions & 0 deletions x/distribution/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/kv"
)

const (
Expand Down Expand Up @@ -60,6 +61,7 @@ func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress)
// 0x02<valAddrLen (1 Byte)><valAddr_Bytes>

// Remove prefix and address length.
kv.AssertKeyAtLeastLength(key, 3)
addr := key[2:]
if len(addr) != int(key[1]) {
panic("unexpected key length")
Expand All @@ -74,6 +76,7 @@ func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) {
// 0x03<accAddrLen (1 Byte)><accAddr_Bytes>

// Remove prefix and address length.
kv.AssertKeyAtLeastLength(key, 3)
addr := key[2:]
if len(addr) != int(key[1]) {
panic("unexpected key length")
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -86,8 +89,10 @@ func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) {
func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) {
// key is in the format:
// 0x04<valAddrLen (1 Byte)><valAddr_Bytes><accAddrLen (1 Byte)><accAddr_Bytes>
kv.AssertKeyAtLeastLength(key, 2)
valAddrLen := int(key[1])
valAddr = sdk.ValAddress(key[2 : 2+valAddrLen])
kv.AssertKeyAtLeastLength(key, 3+valAddrLen)
delAddrLen := int(key[2+valAddrLen])
delAddr = sdk.AccAddress(key[3+valAddrLen:])
if len(delAddr.Bytes()) != delAddrLen {
Expand All @@ -101,8 +106,10 @@ func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delA
func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) {
// key is in the format:
// 0x05<valAddrLen (1 Byte)><valAddr_Bytes><period_Bytes>
kv.AssertKeyAtLeastLength(key, 2)
valAddrLen := int(key[1])
valAddr = sdk.ValAddress(key[2 : 2+valAddrLen])
kv.AssertKeyAtLeastLength(key, 3+valAddrLen)
b := key[2+valAddrLen:]
if len(b) != 8 {
panic("unexpected key length")
Expand All @@ -117,6 +124,7 @@ func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) {
// 0x06<valAddrLen (1 Byte)><valAddr_Bytes>: ValidatorCurrentRewards

// Remove prefix and address length.
kv.AssertKeyAtLeastLength(key, 3)
addr := key[2:]
if len(addr) != int(key[1]) {
panic("unexpected key length")
Expand All @@ -131,6 +139,7 @@ func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddres
// 0x07<valAddrLen (1 Byte)><valAddr_Bytes>: ValidatorCurrentRewards

// Remove prefix and address length.
kv.AssertKeyAtLeastLength(key, 3)
addr := key[2:]
if len(addr) != int(key[1]) {
panic("unexpected key length")
Expand All @@ -143,9 +152,12 @@ func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddres
func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) {
// key is in the format:
// 0x08<valAddrLen (1 Byte)><valAddr_Bytes><height>: ValidatorSlashEvent
kv.AssertKeyAtLeastLength(key, 2)
valAddrLen := int(key[1])
kv.AssertKeyAtLeastLength(key, 3+valAddrLen)
valAddr = key[2 : 2+valAddrLen]
startB := 2 + valAddrLen
kv.AssertKeyAtLeastLength(key, startB+9)
b := key[startB : startB+8] // the next 8 bytes represent the height
height = binary.BigEndian.Uint64(b)
return
Expand Down
2 changes: 2 additions & 0 deletions x/gov/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/kv"
)

const (
Expand Down Expand Up @@ -157,6 +158,7 @@ func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) {
func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) {
// Both Vote and Deposit store keys are of format:
// <prefix (1 Byte)><proposalID (8 bytes)><addrLen (1 Byte)><addr_Bytes>
kv.AssertKeyAtLeastLength(key, 10)
proposalID = GetProposalIDFromBytes(key[1:9])
addr = sdk.AccAddress(key[10:])
return
Expand Down
2 changes: 2 additions & 0 deletions x/slashing/migrations/v040/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/binary"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/kv"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/migrations/v040"
)

Expand Down Expand Up @@ -44,6 +45,7 @@ func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte {

// ValidatorSigningInfoAddress - extract the address from a validator signing info key
func ValidatorSigningInfoAddress(key []byte) (v sdk.ConsAddress) {
kv.AssertKeyAtLeastLength(key, 2)
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
Expand Down
4 changes: 4 additions & 0 deletions x/staking/migrations/v040/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/kv"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/migrations/v040"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
Expand Down Expand Up @@ -66,6 +67,7 @@ func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte {

// Get the validator operator address from LastValidatorPowerKey
func AddressFromLastValidatorPowerKey(key []byte) []byte {
kv.AssertKeyAtLeastLength(key, 2)
return key[1:] // remove prefix bytes
}

Expand Down Expand Up @@ -196,11 +198,13 @@ func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte

// rearranges the ValIndexKey to get the UBDKey
func GetUBDKeyFromValIndexKey(indexKey []byte) []byte {
kv.AssertKeyAtLeastLength(indexKey, 2)
addrs := indexKey[1:] // remove prefix bytes
if len(addrs) != 2*v040auth.AddrLen {
panic("unexpected key length")
}

kv.AssertKeyAtLeastLength(addrs, v040auth.AddrLen+1)
valAddr := addrs[:v040auth.AddrLen]
delAddr := addrs[v040auth.AddrLen:]

Expand Down
14 changes: 14 additions & 0 deletions x/staking/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/kv"
)

const (
Expand Down Expand Up @@ -63,11 +64,13 @@ func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte {

// AddressFromValidatorsKey creates the validator operator address from ValidatorsKey
func AddressFromValidatorsKey(key []byte) []byte {
kv.AssertKeyAtLeastLength(key, 3)
return key[2:] // remove prefix bytes and address length
}

// AddressFromLastValidatorPowerKey creates the validator operator address from LastValidatorPowerKey
func AddressFromLastValidatorPowerKey(key []byte) []byte {
kv.AssertKeyAtLeastLength(key, 3)
return key[2:] // remove prefix bytes and address length
}

Expand Down Expand Up @@ -196,10 +199,13 @@ func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte

// GetUBDKeyFromValIndexKey rearranges the ValIndexKey to get the UBDKey
func GetUBDKeyFromValIndexKey(indexKey []byte) []byte {
kv.AssertKeyAtLeastLength(indexKey, 2)
addrs := indexKey[1:] // remove prefix bytes

valAddrLen := addrs[0]
kv.AssertKeyAtLeastLength(addrs, 2+int(valAddrLen))
valAddr := addrs[1 : 1+valAddrLen]
kv.AssertKeyAtLeastLength(addrs, 3+int(valAddrLen))
delAddr := addrs[valAddrLen+2:]

return GetUBDKey(delAddr, valAddr)
Expand Down Expand Up @@ -273,12 +279,16 @@ func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.V
// GetREDKeyFromValSrcIndexKey rearranges the ValSrcIndexKey to get the REDKey
func GetREDKeyFromValSrcIndexKey(indexKey []byte) []byte {
// note that first byte is prefix byte, which we remove
kv.AssertKeyAtLeastLength(indexKey, 2)
addrs := indexKey[1:]

valSrcAddrLen := addrs[0]
kv.AssertKeyAtLeastLength(addrs, int(valSrcAddrLen)+2)
valSrcAddr := addrs[1 : valSrcAddrLen+1]
delAddrLen := addrs[valSrcAddrLen+1]
kv.AssertKeyAtLeastLength(addrs, int(valSrcAddrLen)+int(delAddrLen)+2)
delAddr := addrs[valSrcAddrLen+2 : valSrcAddrLen+2+delAddrLen]
kv.AssertKeyAtLeastLength(addrs, int(valSrcAddrLen)+int(delAddrLen)+4)
valDstAddr := addrs[valSrcAddrLen+delAddrLen+3:]

return GetREDKey(delAddr, valSrcAddr, valDstAddr)
Expand All @@ -287,12 +297,16 @@ func GetREDKeyFromValSrcIndexKey(indexKey []byte) []byte {
// GetREDKeyFromValDstIndexKey rearranges the ValDstIndexKey to get the REDKey
func GetREDKeyFromValDstIndexKey(indexKey []byte) []byte {
// note that first byte is prefix byte, which we remove
kv.AssertKeyAtLeastLength(indexKey, 2)
addrs := indexKey[1:]

valDstAddrLen := addrs[0]
kv.AssertKeyAtLeastLength(addrs, int(valDstAddrLen)+2)
valDstAddr := addrs[1 : valDstAddrLen+1]
delAddrLen := addrs[valDstAddrLen+1]
kv.AssertKeyAtLeastLength(addrs, int(valDstAddrLen)+int(delAddrLen)+3)
delAddr := addrs[valDstAddrLen+2 : valDstAddrLen+2+delAddrLen]
kv.AssertKeyAtLeastLength(addrs, int(valDstAddrLen)+int(delAddrLen)+4)
valSrcAddr := addrs[valDstAddrLen+delAddrLen+3:]

return GetREDKey(delAddr, valSrcAddr, valDstAddr)
Expand Down