Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,12 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (x/authz) [#24638](https://github.com/cosmos/cosmos-sdk/pull/24638) Fixed a minor bug where the grant key was cast as a string and dumped directly into the error message leading to an error string possibly containing invalid UTF-8.
* (client, client/rpc, x/auth/tx) [#24551](https://github.com/cosmos/cosmos-sdk/pull/24551) Handle cancellation properly when supplying context to client methods.
* (x/epochs) [#24770](https://github.com/cosmos/cosmos-sdk/pull/24770) Fix register of epoch hooks in `InvokeSetHooks`.
* (types/query) [#25049](https://github.com/cosmos/cosmos-sdk/pull/25049) Prevent uint64 overflow in RPC pagination by clamping offset+limit.
* (x/epochs) [#25087](https://github.com/cosmos/cosmos-sdk/pull/25087) Remove redundant error check in BeginBlocker.
* [GHSA-p22h-3m2v-cmgh](https://github.com/cosmos/cosmos-sdk/security/advisories/GHSA-p22h-3m2v-cmgh) Fix x/distribution can halt when historical rewards overflow.
* (x/staking) [#25258](https://github.com/cosmos/cosmos-sdk/pull/25258) Add delegator address to redelegate event.


### Deprecated

* (x/nft) [#24575](https://github.com/cosmos/cosmos-sdk/pull/24575) Deprecate the `x/nft` module in the Cosmos SDK repository. This module will not be maintained to the extent that our core modules will and will be kept in a [legacy repo](https://github.com/cosmos/cosmos-legacy).
Expand Down
14 changes: 14 additions & 0 deletions types/query/pagination.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func Paginate(
onResult func(key, value []byte) error,
) (*PageResponse, error) {
pageRequest = initPageRequestDefaults(pageRequest)
pageRequest = ClampPageRequestLimit(pageRequest)

if pageRequest.Offset > 0 && pageRequest.Key != nil {
return nil, fmt.Errorf("invalid request, either offset or key is expected, got both")
Expand Down Expand Up @@ -158,3 +159,16 @@ func initPageRequestDefaults(pageRequest *PageRequest) *PageRequest {

return &pageRequestCopy
}

// ClampPageRequestLimit returns a safe Limit such that Offset+Limit never overflows uint64.
func ClampPageRequestLimit(pageRequest *PageRequest) *PageRequest {
if pageRequest == nil {
return &PageRequest{}
}

pageRequestCopy := *pageRequest
if pageRequestCopy.Limit > PaginationMaxLimit-pageRequestCopy.Offset {
pageRequestCopy.Limit = PaginationMaxLimit - pageRequestCopy.Offset
}
return &pageRequestCopy
}
14 changes: 14 additions & 0 deletions types/query/pagination_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,3 +375,17 @@ func (s *paginationTestSuite) TestPaginate() {
// Output:
// balances:<denom:"foo0denom" amount:"100" > pagination:<next_key:"foo1denom" total:2 >
}

func (s *paginationTestSuite) TestClampOverflow() {
s.T().Log("verify that Limit is clamped when Offset+Limit would overflow")

pageReq := &query.PageRequest{
Offset: uint64(5),
Limit: ^uint64(0),
}

clamped := query.ClampPageRequestLimit(pageReq)

want := query.PaginationMaxLimit - clamped.Offset
s.Require().Equal(want, clamped.Limit)
}