-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Fix reachable Debug.Assert in StreamPipeReader.AdvanceTo #123810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Replace Debug.Assert with proper validation that throws InvalidOperationException when consumed position is invalid. This handles the case when a SequencePosition from a different PipeReader is passed to AdvanceTo. Add test for the scenario described in the issue. Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request fixes a critical issue where Debug.Assert(_bufferedBytes >= 0) in StreamPipeReader.AdvanceTo was reachable from public API when passing a SequencePosition from a different PipeReader. Debug assertions should never be reachable from public APIs, even under misuse scenarios.
Changes:
- Replace
Debug.Assertwith runtime validation that throwsInvalidOperationExceptionwhenconsumedBytesis invalid - Add test coverage for the scenario where a position from one reader is passed to another reader's
AdvanceTomethod - Move the
_bufferedBytessubtraction to after validation to prevent state corruption
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs | Replaces Debug.Assert with proper runtime validation that checks if consumedBytes is negative or exceeds _bufferedBytes, throwing InvalidOperationException for invalid values |
| src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs | Adds test case verifying that passing a SequencePosition from a different PipeReader to AdvanceTo correctly throws InvalidOperationException |
Description
Debug.Assert(_bufferedBytes >= 0)inStreamPipeReader.AdvanceTois reachable from public API when passing aSequencePositionfrom a differentPipeReader. Debug assertions should never be reachable from public APIs, even under misuse.Pre-change behavior in release builds: The
Debug.Assertwas stripped out, allowing the code to continue with corrupted state._bufferedByteswould become negative after subtracting an invalidconsumedBytesvalue calculated from segments with unrelatedRunningIndexvalues. This led to the reader having an invalid_readHeadpointing to another reader's segment, negative_bufferedBytes, and potentially leaked/corrupted buffer segments.Changes:
Debug.Assertwith validation that throwsInvalidOperationExceptionwhenconsumedBytesis negative or exceeds_bufferedBytesAdvanceWithPositionFromDifferentReaderThrowscovering the reported scenarioNote: This fix validates the symptom (invalid
consumedBytesvalues) rather than explicitly checking segment ownership, which would add O(n) overhead. ThePipeclass has a similarDebug.Assert(_unconsumedBytes >= 0)pattern that may warrant similar treatment.Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.