Skip to content

Commit

Permalink
Fix BinaryReader.ReadChars for fragmented Streams (dotnet#26324) (#26…
Browse files Browse the repository at this point in the history
…356)

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

Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
  • Loading branch information
jkotas authored and dotnet-bot committed Aug 26, 2019
1 parent 1ab6a65 commit b800460
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
22 changes: 22 additions & 0 deletions src/Common/src/CoreLib/System/IO/BinaryReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,28 @@ 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;

// The worst case is charsRemaining = 2 and UTF32Decoder holding onto 3 pending bytes. We need to read just
// one byte in this case.
if (_2BytesPerChar && numBytes > 2)
numBytes -= 2;
}
}

if (numBytes > MaxCharBytesSize)
{
numBytes = MaxCharBytesSize;
Expand Down
2 changes: 1 addition & 1 deletion src/Common/src/CoreLib/System/Text/DecoderNLS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ internal virtual bool HasState
{
get
{
return false;
return _leftoverByteCount != 0;
}
}

Expand Down

0 comments on commit b800460

Please sign in to comment.