diff --git a/pkg/server/datastore/sqlstore/sqlstore.go b/pkg/server/datastore/sqlstore/sqlstore.go index 0342e35750..403f41fffc 100644 --- a/pkg/server/datastore/sqlstore/sqlstore.go +++ b/pkg/server/datastore/sqlstore/sqlstore.go @@ -2032,7 +2032,7 @@ func buildListAttestedNodesQueryCTE(req *datastore.ListAttestedNodesRequest, dbT // Filter by pagination token if req.Pagination != nil && req.Pagination.Token != "" { - token, err := strconv.ParseUint(req.Pagination.Token, 10, 32) + token, err := strconv.ParseUint(req.Pagination.Token, 10, 64) if err != nil { return "", nil, status.Errorf(codes.InvalidArgument, "could not parse token '%v'", req.Pagination.Token) } @@ -2275,7 +2275,7 @@ FROM attested_node_entries N // Filter by pagination token if req.Pagination != nil && req.Pagination.Token != "" { - token, err := strconv.ParseUint(req.Pagination.Token, 10, 32) + token, err := strconv.ParseUint(req.Pagination.Token, 10, 64) if err != nil { return status.Errorf(codes.InvalidArgument, "could not parse token '%v'", req.Pagination.Token) } @@ -3819,7 +3819,7 @@ func appendListRegistrationEntriesFilterQuery(filterExp string, builder *strings } if len(req.Pagination.Token) > 0 { - token, err := strconv.ParseUint(req.Pagination.Token, 10, 32) + token, err := strconv.ParseUint(req.Pagination.Token, 10, 64) if err != nil { return false, nil, status.Errorf(codes.InvalidArgument, "could not parse token '%v'", req.Pagination.Token) } @@ -4083,7 +4083,7 @@ func applyPagination(p *datastore.Pagination, entryTx *gorm.DB) (*gorm.DB, error entryTx = entryTx.Order("id asc").Limit(p.PageSize) if len(p.Token) > 0 { - id, err := strconv.ParseUint(p.Token, 10, 32) + id, err := strconv.ParseUint(p.Token, 10, 64) if err != nil { return nil, status.Errorf(codes.InvalidArgument, "could not parse token '%v'", p.Token) } diff --git a/pkg/server/datastore/sqltest/datastore_suite.go b/pkg/server/datastore/sqltest/datastore_suite.go index 9b11bb78de..bdb74eb270 100644 --- a/pkg/server/datastore/sqltest/datastore_suite.go +++ b/pkg/server/datastore/sqltest/datastore_suite.go @@ -443,9 +443,34 @@ func (s *Suite) TestListBundlesWithPagination() { PageSize: 2, }, }, + { + // Regression test: tokens beyond 32 bits must parse successfully, + // since the underlying ID column is not limited to 32 bits. + // + // This is skipped on postgres below: its ID column is a 32-bit + // integer, so a real deployment can never produce a token this + // large, and postgres itself rejects the literal as out-of-range + // before our code has a chance to run. The scenario this guards + // against (e.g. CockroachDB's bigint unique_rowid()) isn't + // exercised by this conformance suite. + name: "token larger than 32 bits", + expectedList: []*common.Bundle{}, + pagination: &datastore.Pagination{ + Token: "5000000000", + PageSize: 2, + }, + expectedPagination: &datastore.Pagination{ + Token: "", + PageSize: 2, + }, + }, } for _, test := range tests { s.T().Run(test.name, func(t *testing.T) { + if test.name == "token larger than 32 bits" && s.cfg.Dialect == "postgres" { + t.Skip("postgres ID column is a 32-bit integer; this token can never occur in practice") + } + resp, err := s.ds.ListBundles(ctx, &datastore.ListBundlesRequest{ Pagination: test.pagination, })