aboutsummaryrefslogtreecommitdiffstats
path: root/syz-cluster/pkg
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2025-07-04 15:39:18 +0200
committerAleksandr Nogikh <nogikh@google.com>2025-07-08 13:37:33 +0000
commit45106a5dba83f655b716a39fb66477ee3f1d430c (patch)
treec88a1f347a3c6c42afeb6b14f13586619a5d9d94 /syz-cluster/pkg
parent1cde38e3b75bb13c11e17a32b0547fb77fb840fa (diff)
syz-cluster: use shorter report IDs
Since these may be included into email addresses, keep them short.
Diffstat (limited to 'syz-cluster/pkg')
-rw-r--r--syz-cluster/pkg/db/report_repo.go35
-rw-r--r--syz-cluster/pkg/db/spanner.go6
2 files changed, 37 insertions, 4 deletions
diff --git a/syz-cluster/pkg/db/report_repo.go b/syz-cluster/pkg/db/report_repo.go
index 4e039c4a7..c99e4a69d 100644
--- a/syz-cluster/pkg/db/report_repo.go
+++ b/syz-cluster/pkg/db/report_repo.go
@@ -5,9 +5,11 @@ package db
import (
"context"
+ "crypto/rand"
+ "encoding/hex"
+ "fmt"
"cloud.google.com/go/spanner"
- "github.com/google/uuid"
)
type ReportRepository struct {
@@ -27,10 +29,25 @@ func NewReportRepository(client *spanner.Client) *ReportRepository {
}
func (repo *ReportRepository) Insert(ctx context.Context, rep *SessionReport) error {
- if rep.ID == "" {
- rep.ID = uuid.NewString()
+ if rep.ID != "" {
+ return repo.genericEntityOps.Insert(ctx, rep)
}
- return repo.genericEntityOps.Insert(ctx, rep)
+ const attempts = 3
+ for i := 0; i < attempts; i++ {
+ var err error
+ rep.ID, err = randomReportID()
+ if err != nil {
+ return err
+ }
+ err = repo.genericEntityOps.Insert(ctx, rep)
+ if err == errEntityExists {
+ continue
+ }
+ return err
+ }
+ // We shouldn't be getting here until we have sent out billions of reports.
+ // But let's return some error to still exit gracefully.
+ return fmt.Errorf("failed to pick a non-existing report ID")
}
func (repo *ReportRepository) ListNotReported(ctx context.Context, reporter string,
@@ -44,3 +61,13 @@ func (repo *ReportRepository) ListNotReported(ctx context.Context, reporter stri
addLimit(&stmt, limit)
return repo.readEntities(ctx, stmt)
}
+
+// As report ID may be included in the email address, we'd prefer it to be shorter than a typical UUID.
+// A 16 byte hex ID should be good enough.
+func randomReportID() (string, error) {
+ data := make([]byte, 8)
+ if _, err := rand.Read(data); err != nil {
+ return "", err
+ }
+ return hex.EncodeToString(data), nil
+}
diff --git a/syz-cluster/pkg/db/spanner.go b/syz-cluster/pkg/db/spanner.go
index 1aee715f8..1c973ab46 100644
--- a/syz-cluster/pkg/db/spanner.go
+++ b/syz-cluster/pkg/db/spanner.go
@@ -28,6 +28,7 @@ import (
"github.com/golang-migrate/migrate/v4/source/iofs"
"google.golang.org/api/iterator"
"google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
)
type ParsedURI struct {
@@ -325,6 +326,8 @@ func (g *genericEntityOps[EntityType, KeyType]) Update(ctx context.Context, key
return err
}
+var errEntityExists = errors.New("entity already exists")
+
func (g *genericEntityOps[EntityType, KeyType]) Insert(ctx context.Context, obj *EntityType) error {
_, err := g.client.ReadWriteTransaction(ctx,
func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
@@ -334,6 +337,9 @@ func (g *genericEntityOps[EntityType, KeyType]) Insert(ctx context.Context, obj
}
return txn.BufferWrite([]*spanner.Mutation{insert})
})
+ if status.Code(err) == codes.AlreadyExists {
+ return errEntityExists
+ }
return err
}