diff --git a/internal/codeguard/checks/quality/quality_clone.go b/internal/codeguard/checks/quality/quality_clone.go index b6db576..30a73d6 100644 --- a/internal/codeguard/checks/quality/quality_clone.go +++ b/internal/codeguard/checks/quality/quality_clone.go @@ -97,6 +97,16 @@ const ( // candidates are identical to the old per-window byte hashing. func cloneWindowIndex(docs []cloneDocument, threshold int) cloneIndex { index := make(cloneIndex) + hasWindow := false + for _, doc := range docs { + if len(doc.Tokens) >= threshold { + hasWindow = true + break + } + } + if !hasWindow { + return index + } // top = multiplier^(threshold-1), the weight of the token leaving the // window on each slide. top := uint64(1) diff --git a/internal/codeguard/checks/quality/quality_clone_test.go b/internal/codeguard/checks/quality/quality_clone_test.go index f10d4a6..230bdd2 100644 --- a/internal/codeguard/checks/quality/quality_clone_test.go +++ b/internal/codeguard/checks/quality/quality_clone_test.go @@ -16,3 +16,15 @@ func TestCollectCloneCandidatesCapsIdenticalDocuments(t *testing.T) { t.Fatalf("candidate count = %d, want safety cap %d", len(candidates), maxCloneCandidates) } } + +func TestCloneWindowIndexSkipsMultiplierForOversizedThreshold(t *testing.T) { + docs := []cloneDocument{ + {Tokens: []cloneToken{{Hash: 1}}}, + {Tokens: []cloneToken{{Hash: 1}}}, + } + threshold := int(^uint(0) >> 1) + + if index := cloneWindowIndex(docs, threshold); len(index) != 0 { + t.Fatalf("cloneWindowIndex() returned %d windows, want 0", len(index)) + } +}