Skip to content

PipeReaderStream throws when the read buffer is smaller than the examined length #107213

@MihaZupan

Description

@MihaZupan

Description

PipeReaderStream's HandleReadResult implementation calls AdvanceTo with the examined argument set to the same value as consumed.


If the user previously advanced the pipe's examined beyond what is read via the stream, the read will throw.

Reproduction Steps

using System.Buffers;
using System.IO.Pipelines;

var pipe = new Pipe();

pipe.Writer.Write("abc"u8);
await pipe.Writer.FlushAsync();

pipe.Reader.TryRead(out var result);
pipe.Reader.AdvanceTo(result.Buffer.Start, result.Buffer.Slice(result.Buffer.Start, 2).End);

_ = pipe.Reader.AsStream().ReadByte();

Expected behavior

ReadByte returns 'a', advances the pipe's consumed by 1, leaving examined at 2.

Actual behavior

Throws

System.InvalidOperationException: The examined position cannot be less than the previously examined position.
   at System.IO.Pipelines.ThrowHelper.ThrowInvalidOperationException_InvalidExaminedPosition()
   at System.IO.Pipelines.Pipe.AdvanceReader(BufferSegment consumedSegment, Int32 consumedIndex, BufferSegment examinedSegment, Int32 examinedIndex)
   at System.IO.Pipelines.Pipe.AdvanceReader(SequencePosition& consumed, SequencePosition& examined)
   at System.IO.Pipelines.PipeReaderStream.HandleReadResult(ReadResult result, Span`1 buffer)
   at System.IO.Pipelines.PipeReaderStream.HandleReadResult(ReadResult result, Span`1 buffer)
   at System.IO.Pipelines.PipeReaderStream.ReadInternal(Span`1 buffer)
   at System.IO.Pipelines.PipeReaderStream.ReadByte()

Regression?

Not as far as I can tell.

Known Workarounds

Assuming that the examined - start delta is smaller than 4 KB, you can wrap the pipe like so

reader = PipeReader.Create(reader.AsStream());

before doing any reads via the AsStream().

If it's above 4 KB, you can increase the buffer size option on PipeReader.Create.

Configuration

No response

Other information

ASP.NET Core's DuplexPipeStream implementation has the same issue
https://github.com/dotnet/aspnetcore/blob/d630c295110bb4af6b49298671024a545c1642bf/src/Shared/ServerInfrastructure/DuplexPipeStream.cs#L148

Metadata

Metadata

Assignees

Labels

area-System.IO.Pipelinesin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions