🐛 bug: Fix enforcement of Immutable config for some edge cases#3835
🐛 bug: Fix enforcement of Immutable config for some edge cases#3835ReneWerner87 merged 12 commits intov2from
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughReplaces unsafe byte→string conversions with safe, config-aware helpers and adds immutability-aware return paths for Agent.String and multiple Ctx getters; introduces tests validating Agent.String copies body across repeated calls and that context values remain immutable when Config.Immutable is enabled. Changes
Sequence Diagram(s)sequenceDiagram
participant Handler
participant Agent
participant Server
participant AppConfig
Note over Agent,Server: Agent.String call sequence (reused connection)
Handler->>Agent: Agent.String()
activate Agent
Agent->>Server: read response body bytes
Server-->>Agent: body bytes ("body-1")
Agent->>AppConfig: Config.Immutable? → getString/getBytes
AppConfig-->>Agent: returned safe copy or view
Agent-->>Handler: string(body) (copied)
deactivate Agent
Note over Handler,Server: Subsequent call returns new body ("body-2")
Handler->>Agent: Agent.String()
activate Agent
Agent->>Server: read response body bytes
Server-->>Agent: body bytes ("body-2")
Agent->>AppConfig: Config.Immutable? → getString/getBytes
AppConfig-->>Agent: returned safe copy or view
Agent-->>Handler: string(body) (copied)
deactivate Agent
sequenceDiagram
participant Handler
participant Ctx
participant AppConfig
Handler->>Ctx: c.Body()
activate Ctx
Ctx->>AppConfig: Config.Immutable?
alt Immutable = true
AppConfig-->>Ctx: getBytes(copy of bodyBytes)
else Immutable = false
AppConfig-->>Ctx: original bodyBytes (zero-copy view)
end
Ctx-->>Handler: []byte body
deactivate Ctx
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull Request Overview
This PR enhances the immutable mode in Fiber to ensure that all string values returned from request context methods are properly copied when Config.Immutable is enabled, preventing data races and use-after-free bugs when values are accessed after the request lifecycle.
Key changes:
- Added immutability support to additional context methods (
Params,Hostname,IPs,IP,Protocol,Subdomains,Bodyerror handling, and multipart form values) - Fixed a data race in the HTTP client's
String()method by using safe string conversion instead ofutils.UnsafeString() - Updated documentation comments to clarify when immutability applies
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| ctx.go | Added Config.Immutable checks to multiple methods to ensure returned strings are copied; updated documentation for Params() and Hostname() |
| ctx_test.go | Added comprehensive tests to verify immutability behavior across common methods and pointer isolation |
| client.go | Fixed data race in String() method by replacing utils.UnsafeString() with safe string() conversion |
| client_test.go | Added test to verify that reused agents properly copy response bodies |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
ctx.go (3)
425-439: Consider a dedicated string copy helper.The pattern
c.app.getString([]byte(key))andc.app.getString([]byte(val))converts string → bytes → string, which adds unnecessary overhead sincekeyandvaluesare already strings from the multipart form map.Consider adding a dedicated helper like
c.app.copyString(str string) stringthat directly copies strings when immutability is enabled, avoiding the intermediate byte slice conversion.Note: Similar efficiency concerns were raised in past review comments for comparable patterns.
1080-1084: Consider a dedicated string copy helper.Line 1082 uses
c.app.getString([]byte(value))wherevalueis already a string from route parameters. This string → bytes → string conversion adds unnecessary overhead.A dedicated
c.app.copyString(str string) stringhelper would avoid the intermediate byte slice allocation and improve efficiency for this common pattern.Note: This mirrors efficiency concerns raised in past review comments.
1837-1841: Consider a dedicated string copy helper.The pattern
c.app.getString([]byte(subdomain))converts string → bytes → string wheresubdomainis already a string fromstrings.Split(). This adds unnecessary conversion overhead.Using a dedicated string copy helper would be more efficient for this immutability enforcement.
Note: Consistent with efficiency concerns from past review comments.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
client.go(1 hunks)ctx.go(7 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
**/*.go: Apply formatting using gofumpt (Make target: format)
Optimize struct field alignment using betteralign (Make target: betteralign)
Modernize code using gopls modernize (Make target: modernize)
Files:
client.goctx.go
🧠 Learnings (3)
📚 Learning: 2025-09-28T17:39:26.644Z
Learnt from: arturmelanchyk
Repo: gofiber/fiber PR: 3768
File: client/request.go:162-166
Timestamp: 2025-09-28T17:39:26.644Z
Learning: In fasthttp-based code like gofiber, using utils.UnsafeString(key) instead of string(key) is acceptable when values are used immediately within the same call stack and not stored for later use, as it avoids allocations and aligns with fasthttp's zero-allocation design philosophy.
Applied to files:
client.goctx.go
📚 Learning: 2024-11-15T07:56:21.623Z
Learnt from: ReneWerner87
Repo: gofiber/fiber PR: 3161
File: app.go:923-932
Timestamp: 2024-11-15T07:56:21.623Z
Learning: In the Fiber framework, breaking changes are acceptable when moving from version 2 to version 3, including modifications to method signatures such as in the `Test` method in `app.go`.
Applied to files:
ctx.go
📚 Learning: 2024-12-01T10:28:36.011Z
Learnt from: ReneWerner87
Repo: gofiber/fiber PR: 0
File: :0-0
Timestamp: 2024-12-01T10:28:36.011Z
Learning: Fiber currently supports square bracket notation in form data with 'application/x-www-form-urlencoded' content type, but this feature is not available for multipart form data. The implementation for form-urlencoded is in ctx.go (BodyParser method), while multipart form data handling needs enhancement to support this feature.
Applied to files:
ctx.go
🧬 Code graph analysis (1)
ctx.go (1)
helpers.go (1)
HeaderXForwardedHost(1033-1033)
🔇 Additional comments (4)
client.go (1)
800-804: LGTM: Safe string conversion.The change from
utils.UnsafeString(body)tostring(body)correctly ensures the returned string is safe for storage beyond the immediate call stack, aligning with the PR's goal to enforce immutability guarantees.ctx.go (3)
353-355: LGTM: Consistent error handling.Using
c.app.getBytes(err.Error())ensures consistent handling through the app's helper methods.
730-743: LGTM: Correct immutability enforcement for Hostname.The updated implementation correctly:
- Works with byte slices from fasthttp headers
- Handles comma-separated forwarded hosts by trimming at the first comma
- Returns safe string copies via
c.app.getString(hostBytes)when proxy is trusted- Updated documentation reflects the conditional immutability behavior
1883-1885: LGTM: Appropriate byte-to-string conversions.Using
c.app.getString()forMethod()andFullURI()is correct since both return[]bytefrom fasthttp. This ensures safe string copies for the string representation.
|
@gaby can we add some tests for these special cases ? |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
ctx_test.go (1)
2962-3081: LGTM! Comprehensive immutability test that properly validates the fix.The test effectively verifies that context values remain immutable across request lifecycles by:
- Capturing snapshots of context values during handler execution
- Processing a second request with different data (causing context reuse)
- Asserting the first snapshot retains its original values
The coverage is thorough, testing Method, Path, OriginalURL, BaseURL, Protocol, Hostname, route params, query strings, cookies, headers, IP/IPs, subdomains, body, and route path.
Optional enhancements to consider:
Subtests for clarity: Consider organizing the assertions into subtests (e.g.,
t.Run("first_request_data", ...)andt.Run("second_request_data", ...)).Concurrent access: Issue #3236 specifically mentions goroutines. While this test validates immutability across sequential requests, consider adding a companion test that spawns goroutines to access captured values concurrently and verifies no data races occur (potentially with
-raceflag).Documentation: A brief comment at the top explaining this validates immutability guarantees per issue #3236 would help future maintainers.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
ctx_test.go(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
**/*.go: Apply formatting using gofumpt (Make target: format)
Optimize struct field alignment using betteralign (Make target: betteralign)
Modernize code using gopls modernize (Make target: modernize)
Files:
ctx_test.go
🧠 Learnings (4)
📚 Learning: 2024-11-10T23:44:13.704Z
Learnt from: gaby
Repo: gofiber/fiber PR: 3193
File: middleware/adaptor/adaptor.go:111-111
Timestamp: 2024-11-10T23:44:13.704Z
Learning: In the `middleware/adaptor/adaptor.go` file of the Fiber framework, when updating context handling, replacing `c.Context()` with `c.RequestCtx()` is appropriate to access the `fasthttp.RequestCtx`.
Applied to files:
ctx_test.go
📚 Learning: 2024-11-08T04:10:42.990Z
Learnt from: gaby
Repo: gofiber/fiber PR: 3193
File: middleware/cache/cache_test.go:897-897
Timestamp: 2024-11-08T04:10:42.990Z
Learning: In the Fiber framework, `Context()` is being renamed to `RequestCtx()`, and `UserContext()` to `Context()` to improve clarity and align with Go's context conventions.
Applied to files:
ctx_test.go
📚 Learning: 2024-11-15T07:56:21.623Z
Learnt from: ReneWerner87
Repo: gofiber/fiber PR: 3161
File: app.go:923-932
Timestamp: 2024-11-15T07:56:21.623Z
Learning: In the Fiber framework, breaking changes are acceptable when moving from version 2 to version 3, including modifications to method signatures such as in the `Test` method in `app.go`.
Applied to files:
ctx_test.go
📚 Learning: 2024-11-29T12:37:27.581Z
Learnt from: efectn
Repo: gofiber/fiber PR: 3162
File: app_test.go:893-895
Timestamp: 2024-11-29T12:37:27.581Z
Learning: In the `Test_App_ShutdownWithContext` function in `app_test.go`, the `clientDone` channel is used to synchronize the client's request completion before proceeding, eliminating the need for additional `time.Sleep` calls.
Applied to files:
ctx_test.go
🧬 Code graph analysis (1)
ctx_test.go (4)
app.go (2)
New(497-590)Config(121-398)helpers.go (8)
HeaderXForwardedFor(1032-1032)HeaderUserAgent(1043-1043)MethodPost(821-821)HeaderXForwardedHost(1033-1033)HeaderXForwardedProto(1034-1034)HeaderCookie(1007-1007)StatusOK(865-865)MethodPatch(823-823)ctx.go (5)
Ctx(82-100)Ctx(1328-1344)Ctx(1667-1669)Ctx(1672-1688)Ctx(1992-1999)utils/assertions.go (1)
AssertEqual(19-68)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Build (1.22.x, macos-latest)
- GitHub Check: Build (1.21.x, windows-latest)
- GitHub Check: Build (1.23.x, macos-latest)
- GitHub Check: Build (1.22.x, ubuntu-latest)
- GitHub Check: Build (1.23.x, windows-latest)
- GitHub Check: Build (1.20.x, windows-latest)
- GitHub Check: Build (1.19.x, windows-latest)
- GitHub Check: Build (1.18.x, macos-latest)
- GitHub Check: Compare
@ReneWerner87 Added tests for client and ctx |
Summary
c.app.getStringandc.app.getBytesfor Immutable configFixes #3236