Skip to content

System.Console.OpenStandardInput() doesn't return a sane Stream. #61865

@dmbarbour

Description

@dmbarbour

I'm using .NET core 5.0, F#. Wanted to access standard input via Stream abstraction. However, quickly ran into bugs.

Minimal sample program:

    let main argv = 
       use stdin = System.Console.OpenStandardInput()
       printfn "Enter some text."
       printfn "First byte: %d" (stdin.ReadByte())

This doesn't work for larger inputs on the interactive command line. For example, it doesn't work for abcdefghijklmnop<ENTER>. It reports a System.ArgumentException (debug stack below).

Note that it does work with one byte fewer, i.e. if we have just 16 bytes in the input abcdefghijklmno<ENTER> will give the correct 97 value. It also works if piping standard input from another source, e.g. echo "abcdefghijklmnopqrstuvwxyz" | dotnet run will give the correct 97 value. So the issue seems specific to the command line interactive input.

If I use System.Console.Read() instead, I also receive the correct 97 value for larger inputs, though I get 8594 (0x2192) instead of a byte if my first character is Unicode right arrow . I actually wanted bytes as originally input for my use case, was hoping to avoid all the implicit conversions to chars then back to UTF-8.

Configuration

Using Linux (Ubuntu 20.04) x86
Dotnet version 5.0.403

Regression?

I haven't tried on other configurations.

Other information

$ dotnet run
Enter some text.
abcdefghijklmnop
Unhandled exception. System.ArgumentException: The output byte buffer is too small to contain the encoded data, encoding 'Unicode (UTF-8)' fallback 'System.Text.EncoderReplacementFallback'. (Parameter 'bytes')
   at System.Text.Encoding.ThrowBytesOverflow()
   at System.Text.Encoding.ThrowBytesOverflow(EncoderNLS encoder, Boolean nothingEncoded)
   at System.Text.Encoding.GetBytesWithFallback(ReadOnlySpan`1 chars, Int32 originalCharsLength, Span`1 bytes, Int32 originalBytesLength, EncoderNLS encoder)
   at System.Text.Encoding.GetBytesWithFallback(Char* pOriginalChars, Int32 originalCharCount, Byte* pOriginalBytes, Int32 originalByteCount, Int32 charsConsumedSoFar, Int32 bytesWrittenSoFar, EncoderNLS encoder)
   at System.Text.Encoding.GetBytes(Char* pChars, Int32 charCount, Byte* pBytes, Int32 byteCount, EncoderNLS encoder)
   at System.Text.EncoderNLS.Convert(Char* chars, Int32 charCount, Byte* bytes, Int32 byteCount, Boolean flush, Int32& charsUsed, Int32& bytesUsed, Boolean& completed)
   at System.Text.Encoder.Convert(ReadOnlySpan`1 chars, Span`1 bytes, Boolean flush, Int32& charsUsed, Int32& bytesUsed, Boolean& completed)
   at System.IO.StdInReader.ReadLine(Byte[] buffer, Int32 offset, Int32 count)
   at System.ConsolePal.UnixConsoleStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.Stream.ReadByte()
   at Program.main(String[] argv) in /home/dmbarbour/projects/tst/Program.fs:line 9

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions