From 654cd7e0d39c16fe3adec6f67a27eb3b1304c35d Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 26 Aug 2019 08:04:09 -0700 Subject: [PATCH] [release/3.0] Fix BinaryReader.ReadChars for fragmented Streams (#26324) (#26356) 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 --- .../shared/System/IO/BinaryReader.cs | 22 ++++++++++++++++++++++ .../shared/System/Text/DecoderNLS.cs | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs b/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs index 560c998..037088c 100644 --- a/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs +++ b/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs @@ -390,6 +390,28 @@ namespace System.IO { 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; diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderNLS.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderNLS.cs index 184d59d..8cb3fff 100644 --- a/src/System.Private.CoreLib/shared/System/Text/DecoderNLS.cs +++ b/src/System.Private.CoreLib/shared/System/Text/DecoderNLS.cs @@ -227,7 +227,7 @@ namespace System.Text { get { - return false; + return _leftoverByteCount != 0; } } -- 2.7.4