Skip to content

Commit

Permalink
Fix BinaryReader.ReadChars for fragmented Streams
Browse files Browse the repository at this point in the history
BinaryReader.ReadChars incorrectly read more than necessary from the underlying Stream when multi-byte characters straddled the read chunks.

Fixes https://github.com/dotnet/corefx/issues/40455
  • Loading branch information
jkotas committed Aug 22, 2019
1 parent 42e189b commit 43a04b0
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
19 changes: 19 additions & 0 deletions src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,25 @@ private int InternalReadChars(Span<char> buffer)
{
numBytes <<= 1;
}

// We do not want to read even a single byte more than necessary.
//
// Subtract pending bytes that the decoder may be holding onto. This assumes that each
// decoded char corresponds to one or more bytes. Note that custom encodings or encodings with
// a custom replacement sequence may violate this assumption.
if (numBytes > 1)
{
DecoderNLS? decoder = _decoder as DecoderNLS;
// For internal decoders, we can check whether the decoder has any pending state.
// For custom decoders, assume that the decoder has pending state.
if (decoder == null || decoder.HasState)
{
numBytes -= 1;
if (_2BytesPerChar && numBytes > 2)
numBytes -= 2;
}
}

if (numBytes > MaxCharBytesSize)
{
numBytes = MaxCharBytesSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public override unsafe void Convert(byte* bytes, int byteCount,
public bool MustFlush => _mustFlush;

// Anything left in our decoder?
internal virtual bool HasState => false;
internal virtual bool HasState => _leftoverByteCount != 0;

// Allow encoding to clear our must flush instead of throwing (in ThrowCharsOverflow)
internal void ClearMustFlush()
Expand Down

0 comments on commit 43a04b0

Please sign in to comment.