Skip to content

Conversation

@WeidiDeng
Copy link
Member

Assistance Disclosure

No AI is used.

Some of the modulo calculations have been changed to IntN for simplicity.

@diffray-bot
Copy link

Changes Summary

This PR updates Caddy to use Go's math/rand/v2 package (introduced in Go 1.22) instead of the legacy math/rand package. The changes include replacing deprecated methods like Intn() with IntN(), Int63() with Int64(), and updating random source initialization with ChaCha8-based generators.

Type: refactoring

Components Affected: HTTP authentication (basicauth), HTTP error handling, File server (static files), Reverse proxy (selection policies, streaming, upstreams), ACME server, FastCGI client, Integration tests

Files Changed
File Summary Change Impact
...orkspace/caddytest/integration/listener_test.go Updated import from math/rand to math/rand/v2 and replaced rand.New(rand.NewSource(0)).Read() with rand.NewChaCha8([32]byte{}).Read() ✏️ 🟢
...kspace/modules/caddyhttp/caddyauth/basicauth.go Updated import to math/rand/v2 and replaced weakrand.Intn() call with weakrand.IntN() ✏️ 🟢
/tmp/workspace/modules/caddyhttp/errors.go Updated import to math/rand/v2 and replaced weakrand.Int63()%int64(len(dict)) with weakrand.IntN(len(dict)) ✏️ 🟢
...ace/modules/caddyhttp/fileserver/staticfiles.go Updated import to math/rand/v2 and replaced weakrand.Intn() call with weakrand.IntN() ✏️ 🟢
...s/caddyhttp/reverseproxy/fastcgi/client_test.go Updated import to math/rand/v2 and replaced rand.Int63() with rand.Int64() in test file ✏️ 🟢
...modules/caddyhttp/reverseproxy/httptransport.go Updated import to math/rand/v2 and replaced weakrand.Intn() call with weakrand.IntN() ✏️ 🟢
...les/caddyhttp/reverseproxy/selectionpolicies.go Updated import to math/rand/v2 and replaced multiple weakrand.Intn() and (weakrand.Int() % count) patterns with weakrand.IntN() equivalents ✏️ 🟢
...ace/modules/caddyhttp/reverseproxy/streaming.go Updated import from math/rand to math/rand/v2 ✏️ 🟢
...ace/modules/caddyhttp/reverseproxy/upstreams.go Updated import to math/rand/v2 and replaced weakrand.Intn() calls with weakrand.IntN() ✏️ 🟢
...space/modules/caddypki/acmeserver/acmeserver.go Updated import to math/rand/v2 and replaced weakrand.Intn() call with weakrand.IntN() ✏️ 🟢
Architecture Impact
  • Dependencies: Updated from math/rand to math/rand/v2 (Go stdlib)

Risk Areas: Random number generation correctness - IntN() has different semantics than Intn(), Modulo operation replacement - Converting (weakrand.Int() % count) == 0 to weakrand.IntN(count) == 0 changes the random distribution slightly but achieves equivalent logic, ChaCha8 initialization - listener_test.go uses rand.NewChaCha8([32]byte{}) which initializes with a zero seed for deterministic testing

Suggestions
  • Verify that random selection algorithms (particularly in reverse proxy policies) produce correct load balancing behavior with the new IntN() method
  • Confirm the zero-seed ChaCha8 initialization in listener_test.go produces reproducible test behavior as intended
  • Test the error string generation with new IntN() method to ensure error pages are still properly randomized

Full review in progress... | Powered by diffray

// Go maps are "nondeterministic" not actually random,
// so although we could just chop off the "front" of the
// map with less code, this is a heavily skewed eviction
// strategy; generating random numbers is cheap and

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 CRITICAL - Off-by-one error in cache eviction loop condition
Agent: go

Category: bug

Description:
Loop condition 'deleted <= numToDelete' causes deletion of numToDelete+1 items instead of numToDelete. With numToDelete=10, the loop runs for deleted values 0 through 10 inclusive (11 iterations), deleting 11 items instead of 10.

Suggestion:
Change '<=' to '<' on line 240: 'for deleted := 0; deleted < numToDelete; deleted++'

Confidence: 95%
Rule: bug_slice_bounds_go
Review ID: 9bac5f9f-38e7-46a1-add2-7c064de630b1
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

Comment on lines +247 to 250
rnd := weakrand.IntN(len(c.cache))
i := 0
for key := range c.cache {
if i == rnd {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 HIGH - Inefficient O(n*m) cache eviction with repeated map traversals
Agent: go

Category: performance

Description:
The makeRoom() function performs numToDelete iterations, each generating a random index and iterating through the entire map to find and delete that element. This creates O(n*m) complexity where n is cache size and m is items to delete.

Suggestion:
Optimize by collecting all cache keys into a slice once, shuffling, and deleting the first numToDelete keys in a single pass for O(n) complexity.

Confidence: 85%
Rule: go_use_defer_to_release_resources
Review ID: 9bac5f9f-38e7-46a1-add2-7c064de630b1
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

// 1 more than an MB
body := make([]byte, uploadSize)
rand.New(rand.NewSource(0)).Read(body)
rand.NewChaCha8([32]byte{}).Read(body)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM - Zero-initialized random seed produces deterministic test data
Agent: go

Category: quality

Description:
Using 'rand.NewChaCha8([32]byte{})' with a zero seed produces identical test data on every run. While this may be intentional for reproducibility, the test name suggests testing with varied data.

Suggestion:
If determinism is intended, add a comment explaining the choice. If varied data is desired, use a non-zero or time-based seed.

Confidence: 65%
Rule: qual_misleading_names_go
Review ID: 9bac5f9f-38e7-46a1-add2-7c064de630b1
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

@diffray-bot
Copy link

Review Summary

Free public review - Want AI code reviews on your PRs? Check out diffray.ai

Validated 9 issues: 5 kept (1 critical off-by-one bug, 2 performance/quality concerns, 2 security/quality), 4 filtered (2 incorrect API claims, 1 false positive on guarded code, 1 low-value exported field concern)

Issues Found: 5

💬 See 3 individual line comment(s) for details.

📋 Full issue list (click to expand)

🔴 CRITICAL - Off-by-one error in cache eviction loop condition

Agent: go

Category: bug

File: modules/caddyhttp/caddyauth/basicauth.go:244

Description: Loop condition 'deleted <= numToDelete' causes deletion of numToDelete+1 items instead of numToDelete. With numToDelete=10, the loop runs for deleted values 0 through 10 inclusive (11 iterations), deleting 11 items instead of 10.

Suggestion: Change '<=' to '<' on line 240: 'for deleted := 0; deleted < numToDelete; deleted++'

Confidence: 95%

Rule: bug_slice_bounds_go


🟠 HIGH - Inefficient O(n*m) cache eviction with repeated map traversals

Agent: go

Category: performance

File: modules/caddyhttp/caddyauth/basicauth.go:247-250

Description: The makeRoom() function performs numToDelete iterations, each generating a random index and iterating through the entire map to find and delete that element. This creates O(n*m) complexity where n is cache size and m is items to delete.

Suggestion: Optimize by collecting all cache keys into a slice once, shuffling, and deleting the first numToDelete keys in a single pass for O(n) complexity.

Confidence: 85%

Rule: go_use_defer_to_release_resources


🟡 MEDIUM - Zero-initialized random seed produces deterministic test data

Agent: go

Category: quality

File: caddytest/integration/listener_test.go:57

Description: Using 'rand.NewChaCha8([32]byte{})' with a zero seed produces identical test data on every run. While this may be intentional for reproducibility, the test name suggests testing with varied data.

Suggestion: If determinism is intended, add a comment explaining the choice. If varied data is desired, use a non-zero or time-based seed.

Confidence: 65%

Rule: qual_misleading_names_go


🟡 MEDIUM - Slice aliasing: defaultIndexNames assigned without copy

Agent: security

Category: security

File: modules/caddyhttp/fileserver/staticfiles.go:201-203

Description: The IndexNames field is assigned the module-level defaultIndexNames slice directly without a defensive copy. If IndexNames is modified later, it will corrupt the shared default.

Suggestion: Create a defensive copy: fsrv.IndexNames = append([]string(nil), defaultIndexNames...)

Confidence: 75%

Rule: go_copy_slices_and_maps_at_boundaries


🟡 MEDIUM - Global variable test isolation violation - globalt not restored

Agent: testing

Category: quality

File: modules/caddyhttp/reverseproxy/fastcgi/client_test.go:55-214

Description: The global variable globalt (*testing.T) is written to in DisabledTest without being restored via defer, violating test isolation principles.

Suggestion: Remove the global globalt variable and pass *testing.T as a parameter through the function call chain to maintain test isolation.

Confidence: 80%

Rule: go_test_isolation_violations


ℹ️ 2 issue(s) outside PR diff (click to expand)

These issues were found in lines not modified in this PR.

🟡 MEDIUM - Slice aliasing: defaultIndexNames assigned without copy

Agent: security

Category: security

File: modules/caddyhttp/fileserver/staticfiles.go:201-203

Description: The IndexNames field is assigned the module-level defaultIndexNames slice directly without a defensive copy. If IndexNames is modified later, it will corrupt the shared default.

Suggestion: Create a defensive copy: fsrv.IndexNames = append([]string(nil), defaultIndexNames...)

Confidence: 75%

Rule: go_copy_slices_and_maps_at_boundaries


🟡 MEDIUM - Global variable test isolation violation - globalt not restored

Agent: testing

Category: quality

File: modules/caddyhttp/reverseproxy/fastcgi/client_test.go:55-214

Description: The global variable globalt (*testing.T) is written to in DisabledTest without being restored via defer, violating test isolation principles.

Suggestion: Remove the global globalt variable and pass *testing.T as a parameter through the function call chain to maintain test isolation.

Confidence: 80%

Rule: go_test_isolation_violations



Review ID: 9bac5f9f-38e7-46a1-add2-7c064de630b1
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants