Clone copilot SessionConfig.Tools before appending per-run tools - #595
Clone copilot SessionConfig.Tools before appending per-run tools#595PratikDhanave wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes a concurrency/data-race risk in the Copilot provider’s session configuration building by ensuring each run owns its own SessionConfig.Tools slice before per-run tools are appended.
Changes:
- Clone
SessionConfig.ToolsincopySessionConfigto avoid aliasing provider-held config state. - Clone
SessionConfig.ToolsincopyResumeSessionConfigfor the same reason when resuming sessions. - Add internal tests validating that per-run tool appends do not share backing arrays with the provider config (or across runs).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| provider/copilotprovider/copilot.go | Clones Tools slices in session config copy helpers to prevent shared backing arrays and data races when appending per-run tools. |
| provider/copilotprovider/copilot_internal_test.go | Adds regression tests ensuring per-run tool appends do not mutate or alias the provider’s shared SessionConfig.Tools backing array. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dd36a56 to
c32f8e8
Compare
This comment has been minimized.
This comment has been minimized.
c32f8e8 to
b009dec
Compare
This comment has been minimized.
This comment has been minimized.
copySessionConfig shallow-copied the source struct, so the clone's Tools field aliased the shared provider-held SessionConfig.Tools backing array, and copyResumeSessionConfig assigned it directly. sessionConfig and resumeSessionConfig then append per-run tools in place, so a caller slice with spare capacity is written through, and two concurrent runs of the same agent race on the same backing array. Clone Tools before appending so each run gets its own slice.
b009dec to
64e5191
Compare
Parity Review: No Cross-Repo Consistency IssuesThis PR fixes a data race in two unexported helper functions — Scope verdict: Out of scope for parity review. No exported identifiers were added, removed, or changed. No user-visible defaults, option shapes, or runtime behaviors were altered. Label status: No Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
What
copySessionConfigdidclone := *source, a shallow copy that leavesclone.Toolsaliasing the shared provider-heldp.cfg.SessionConfig.Tools, andcopyResumeSessionConfigassignedTools: source.Toolsdirectly. BothsessionConfigandresumeSessionConfigthen runcfg.Tools = append(cfg.Tools, copilotTools(options)...)per run.When the user-supplied
Toolsslice has spare capacity, that append writes the per-run tools into the caller's backing array, and two concurrent runs of the same agent write into the same index — a data race and a corrupted tool list.The fix clones the slice before appending:
clone.Tools = slices.Clone(source.Tools)andTools: slices.Clone(source.Tools).slicesis already imported.Why
Each run must own its
Toolsslice so appending per-run tools never mutates the shared session config or another concurrent run. This mirrors the clone-before-append fixes already merged in #529 and #555, keeping copilot session setup consistent with the rest of the port.Testing
Added
copilot_internal_test.gocovering bothsessionConfigandresumeSessionConfig: a provider whoseSessionConfig.Toolshas spare capacity is invoked twice with a per-run tool, asserting the shared config is unchanged and that neither returned slice shares a backing array with the shared config or with each other. The tests fail before the fix and pass after.go build ./...,go vet ./provider/copilotprovider/..., andgo test ./provider/copilotprovider/...all pass.