fix(fuzz): concurrent map writes in multipart form parsing#7291
fix(fuzz): concurrent map writes in multipart form parsing#7291dwisiswant0 merged 1 commit intodevfrom
Conversation
Neo - PR Security ReviewNo security issues found Highlights
Comment |
WalkthroughThis PR fixes a fatal concurrency issue in multipart form data fuzzing by instantiating a new decoder per request instead of reusing a shared singleton, storing the decoder instance for consistent use throughout request processing. Changes
Sequence DiagramsequenceDiagram
participant G1 as Goroutine 1<br/>(Target A)
participant G2 as Goroutine 2<br/>(Target B)
participant Body as Body.parseBody()
participant DF as dataformat
participant Value as Value.encoder
par Concurrent Requests
G1->>Body: parseBody(req_A)
G2->>Body: parseBody(req_B)
end
rect rgba(255, 100, 100, 0.5)
Note over G1,G2: OLD (Race Condition)
G1->>DF: Get("multipart/form-data")<br/>← returns singleton
G2->>DF: Get("multipart/form-data")<br/>← same singleton!
G1->>DF: singleton.ParseBoundary(contentType_A)<br/>write to boundary
G2->>DF: singleton.ParseBoundary(contentType_B)<br/>write to boundary (DATA RACE)
end
rect rgba(100, 200, 100, 0.5)
Note over G1,G2: NEW (Fixed)
G1->>DF: NewMultiPartForm()<br/>← new instance
G2->>DF: NewMultiPartForm()<br/>← new instance
G1->>DF: decoder_A.ParseBoundary(contentType_A)
G2->>DF: decoder_B.ParseBoundary(contentType_B)
G1->>Value: encoder = decoder_A
G2->>Value: encoder = decoder_B
G1->>Value: encode() uses encoder_A
G2->>Value: encode() uses encoder_B
end
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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.
🧹 Nitpick comments (1)
pkg/fuzz/component/value.go (1)
41-48: Shallow copy ofencodershares mutable state between clones.The
Clone()method copies theencoderreference, meaning original and clonedValueinstances share the sameMultiPartFormpointer. While concurrentEncode()calls are safe (read-only onboundary/filesMetadata), this could become a latent issue if a caller re-parses the original while clones are in use.If
Clone()is used to spawn concurrent mutations of the same base request, consider creating a fresh encoder copy to fully isolate state. Given the typical usage pattern (each request gets its ownParse()call), this is low risk but worth noting for future-proofing.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/fuzz/component/value.go` around lines 41 - 48, Value.Clone currently copies the encoder pointer, sharing Mutable MultiPartForm state between original and clone; update Value.Clone so it deep-copies the encoder instead of copying the reference — if v.encoder != nil create a new MultiPartForm (or call a MultiPartForm.Clone method if available) and copy over its boundary and filesMetadata (and any other internal fields) into the new encoder, then assign that new encoder to the cloned Value; reference Value.Clone, the encoder field, and the MultiPartForm type (or a new Clone method on it) when making this change so clones are fully isolated from mutations to the original.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@pkg/fuzz/component/value.go`:
- Around line 41-48: Value.Clone currently copies the encoder pointer, sharing
Mutable MultiPartForm state between original and clone; update Value.Clone so it
deep-copies the encoder instead of copying the reference — if v.encoder != nil
create a new MultiPartForm (or call a MultiPartForm.Clone method if available)
and copy over its boundary and filesMetadata (and any other internal fields)
into the new encoder, then assign that new encoder to the cloned Value;
reference Value.Clone, the encoder field, and the MultiPartForm type (or a new
Clone method on it) when making this change so clones are fully isolated from
mutations to the original.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f7d64e70-40b7-4074-bbdb-e818e3a8a939
📒 Files selected for processing (3)
pkg/fuzz/component/body.gopkg/fuzz/component/body_test.gopkg/fuzz/component/value.go
Proposed changes
Close #7028
Checklist
Summary by CodeRabbit
Bug Fixes
Tests