What changed, and why it matters
This commit changes internal database configuration values from signed integers (int/int32) to unsigned integers (uint32). It is a code-quality and type-safety cleanup, not a fix for an active security vulnerability. The change removes the theoretical possibility that a negative page or batch size could be supplied, which could cause loops or errors, but there is no evidence this was exploitable by an attacker.
No urgent action required. Treat as a routine hardening change. Review whether uint32 upper bounds are validated elsewhere to avoid extremely large values causing excessive memory use.
Security signals we found
Type narrowing from signed to unsigned integer for configuration parameters
Prevents negative MaxBatchSize/MaxPageSize values at the type level
No input validation added; relies on Go's type system
No explicit security relevance disclosed by the vendor
Evidence from the diff
The patch converts QueryConfig.MaxBatchSize from int to uint32 and MaxPageSize from int32 to uint32. Call sites are updated with explicit int casts where needed. This prevents negative values from being accepted for these configuration parameters. The commit does not add new validation logic or change behavior for any previously valid positive values; it only narrows the type domain. No memory-safety bug, injection flaw, or authentication bypass is present in the diff.
Changed components
sqldb/paginate.go QueryConfig structgraph/db/sql_migration.go batch size comparisonsgraph/db/benchmark_test.go benchmark configurationsqldb/paginate_test.go test fixturesInspect captured patch +18 / −18
diff --git a/graph/db/benchmark_test.go b/graph/db/benchmark_test.go
index 58b8cb3..bdb7954 100644
--- a/graph/db/benchmark_test.go
+++ b/graph/db/benchmark_test.go
@@ -788,13 +788,13 @@ func BenchmarkFindOptimalSQLQueryConfig(b *testing.B) {
// Set the various page sizes we want to test.
//
// NOTE: these are the sqlite paging testing values.
- testSizes := []int{20, 50, 100, 150, 500}
+ testSizes := []uint32{20, 50, 100, 150, 500}
configOption := "MaxPageSize"
if testBatching {
configOption = "MaxBatchSize"
- testSizes = []int{
+ testSizes = []uint32{
50, 100, 150, 200, 250, 300, 350,
}
}
@@ -806,10 +806,10 @@ func BenchmarkFindOptimalSQLQueryConfig(b *testing.B) {
// Set the various page sizes we want to test.
//
// NOTE: these are the postgres paging values.
- testSizes = []int{5000, 7000, 10000, 12000}
+ testSizes = []uint32{5000, 7000, 10000, 12000}
if testBatching {
- testSizes = []int{
+ testSizes = []uint32{
1000, 2000, 5000, 7000, 10000,
}
}
@@ -828,7 +828,7 @@ func BenchmarkFindOptimalSQLQueryConfig(b *testing.B) {
if testBatching {
cfg.MaxBatchSize = size
} else {
- cfg.MaxPageSize = int32(size)
+ cfg.MaxPageSize = size
}
store := connectNativeSQLite(
diff --git a/graph/db/sql_migration.go b/graph/db/sql_migration.go
index 0584914..5aea3d3 100644
--- a/graph/db/sql_migration.go
+++ b/graph/db/sql_migration.go
@@ -283,7 +283,7 @@ func migrateNodes(ctx context.Context, cfg *sqldb.QueryConfig,
batch[id] = node
// Validate batch when full.
- if len(batch) >= cfg.MaxBatchSize {
+ if len(batch) >= int(cfg.MaxBatchSize) {
err := validateBatch()
if err != nil {
return fmt.Errorf("batch validation failed: %w",
@@ -548,7 +548,7 @@ func migrateChannelsAndPolicies(ctx context.Context, cfg *SQLStoreConfig,
dbInfo: dbChanInfo,
}
- if len(batch) >= cfg.QueryCfg.MaxBatchSize {
+ if len(batch) >= int(cfg.QueryCfg.MaxBatchSize) {
// Do batch validation.
err := validateMigratedChannels(ctx, cfg, sqlDB, batch)
if err != nil {
@@ -902,7 +902,7 @@ func migratePruneLog(ctx context.Context, cfg *sqldb.QueryConfig,
batch[height] = *hash
// Validate batch when full.
- if len(batch) >= cfg.MaxBatchSize {
+ if len(batch) >= int(cfg.MaxBatchSize) {
err := validateBatch()
if err != nil {
return fmt.Errorf("batch "+
@@ -1070,7 +1070,7 @@ func migrateClosedSCIDIndex(ctx context.Context, cfg *sqldb.QueryConfig,
batch = append(batch, chanIDB)
// Validate batch when full.
- if len(batch) >= cfg.MaxBatchSize {
+ if len(batch) >= int(cfg.MaxBatchSize) {
err := validateBatch()
if err != nil {
return fmt.Errorf("batch validation failed: %w",
@@ -1251,7 +1251,7 @@ func migrateZombieIndex(ctx context.Context, cfg *sqldb.QueryConfig,
}
// Validate batch when full.
- if len(batch) >= cfg.MaxBatchSize {
+ if len(batch) >= int(cfg.MaxBatchSize) {
err := validateBatch()
if err != nil {
return fmt.Errorf("batch validation failed: %w",
diff --git a/sqldb/paginate.go b/sqldb/paginate.go
index 17e2fd4..4fd2a9d 100644
--- a/sqldb/paginate.go
+++ b/sqldb/paginate.go
@@ -37,11 +37,11 @@ const (
type QueryConfig struct {
// MaxBatchSize is the maximum number of items included in a batch
// query IN clauses list.
- MaxBatchSize int `long:"max-batch-size" description:"The maximum number of items to include in a batch query IN clause. This is used for queries that fetch results based on a list of identifiers."`
+ MaxBatchSize uint32 `long:"max-batch-size" description:"The maximum number of items to include in a batch query IN clause. This is used for queries that fetch results based on a list of identifiers."`
// MaxPageSize is the maximum number of items returned in a single page
// of results. This is used for paginated queries.
- MaxPageSize int32 `long:"max-page-size" description:"The maximum number of items to return in a single page of results. This is used for paginated queries."`
+ MaxPageSize uint32 `long:"max-page-size" description:"The maximum number of items to return in a single page of results. This is used for paginated queries."`
}
// Validate checks that the QueryConfig values are valid.
@@ -121,9 +121,9 @@ func ExecuteBatchQuery[I any, T any, R any](ctx context.Context,
}
// Process items in pages.
- for i := 0; i < len(inputItems); i += cfg.MaxBatchSize {
+ for i := 0; i < len(inputItems); i += int(cfg.MaxBatchSize) {
// Calculate the end index for this page.
- end := i + cfg.MaxBatchSize
+ end := i + int(cfg.MaxBatchSize)
if end > len(inputItems) {
end = len(inputItems)
}
@@ -189,7 +189,7 @@ func ExecutePaginatedQuery[C any, T any](ctx context.Context, cfg *QueryConfig,
for {
// Fetch the next page.
- items, err := queryFunc(ctx, cursor, cfg.MaxPageSize)
+ items, err := queryFunc(ctx, cursor, int32(cfg.MaxPageSize))
if err != nil {
return fmt.Errorf("failed to fetch page with "+
"cursor %v: %w", cursor, err)
@@ -265,7 +265,7 @@ func ExecuteCollectAndBatchWithSharedDataQuery[C any, T any, I any, D any](
for {
// Step 1: Fetch the next page of items.
- items, err := pageQueryFunc(ctx, cursor, cfg.MaxPageSize)
+ items, err := pageQueryFunc(ctx, cursor, int32(cfg.MaxPageSize))
if err != nil {
return fmt.Errorf("failed to fetch page with "+
"cursor %v: %w", cursor, err)
diff --git a/sqldb/paginate_test.go b/sqldb/paginate_test.go
index f62bf65..20abf42 100644
--- a/sqldb/paginate_test.go
+++ b/sqldb/paginate_test.go
@@ -341,7 +341,7 @@ func TestExecutePaginatedQuery(t *testing.T) {
tests := []struct {
name string
- pageSize int32
+ pageSize uint32
allItems []testItem
initialCursor int64
queryError error
@@ -592,7 +592,7 @@ func TestExecuteCollectAndBatchWithSharedDataQuery(t *testing.T) {
tests := []struct {
name string
- maxPageSize int32
+ maxPageSize uint32
allRows []channelRow
initialCursor int64
pageQueryError error
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.