Azure / azure-functions-dotnet-worker

Azure Functions out-of-process .NET language worker
MIT License
429 stars 183 forks source link

ReadAsStringAsync does not supply a default encoding #1986

Closed endizhupani closed 1 year ago

endizhupani commented 1 year ago

Issue: Calling Microsoft.Azure.Functions.Worker.Http.HttpRequestDataExtensions.ReadAsStringAsync without specifying the encoding results in a NullReferenceException.

The documentation for HttpRequestDataExtensions.ReadAsStringAsync states that the encoding parameter defaults to UTF-8.

Expected behaviour A call such as this: await req.ReadAsStringAsync() works and UTF-8 as the default encoding.

kshyju commented 1 year ago

@endizhupani Can you share the full stack trace of the null reference exception you are getting. I am not able to replicate the NRE when using the ReadAsStringAsync extension method. If you may also share the code you used to replicate the issue, that would be great.

The ReadAsStringAsync method uses StreamReader constructor and if an encoding value is not passed as a parameter to this constructor, it will use the default value which is UTF8.

endizhupani commented 1 year ago

@kshyju Of course. Just for further info, the target framework for my functions project is net48, so I'm using .NET Framework.

Stack trace (timestamps are there because I copied the function logs directly):

Function 'worftopdfconversion', Invocation id 'acb921dc-68d5-4cf5-8cb6-aebcbe133f11': An exception was thrown by the invocation.
[2023-10-25T07:29:12.625Z] Result: Function 'worftopdfconversion', Invocation id 'acb921dc-68d5-4cf5-8cb6-aebcbe133f11': An exception was thrown by the invocation.
Exception: System.AggregateException: One or more errors occurred. ---> System.ArgumentNullException: Value cannot be null.
[2023-10-25T07:29:12.626Z] Parameter name: encoding
[2023-10-25T07:29:12.626Z]    at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen)
[2023-10-25T07:29:12.627Z]    at Microsoft.Azure.Functions.Worker.Http.HttpRequestDataExtensions.<ReadAsStringAsync>d__0.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\Http\HttpRequestDataExtensions.cs:line 40
[2023-10-25T07:29:12.628Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.629Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.630Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.630Z]    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
[2023-10-25T07:29:12.631Z]    at Crm.WordToPdfConversion.FileConverter.<Run>d__2.MoveNext() in C:\Users\endi.zhupani\source\repos\Ximea.Services\src\legacy\Crm.WordToPdfConversion\FileConverter.cs:line 33
[2023-10-25T07:29:12.632Z]    --- End of inner exception stack trace ---
[2023-10-25T07:29:12.633Z]    at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
[2023-10-25T07:29:12.634Z]    at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker`2.<>c.<InvokeAsync>b__6_0(Task`1 t) in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionInvoker.cs:line 32
[2023-10-25T07:29:12.635Z]    at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
[2023-10-25T07:29:12.636Z]    at System.Threading.Tasks.Task.Execute()
[2023-10-25T07:29:12.636Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.637Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.638Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.639Z]    at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.<ExecuteAsync>d__4.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 45
[2023-10-25T07:29:12.640Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.641Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.642Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.642Z]    at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.<Invoke>d__0.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 15
[2023-10-25T07:29:12.643Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.644Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.645Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.645Z]    at Microsoft.Azure.Functions.Worker.FunctionsApplication.<InvokeFunctionAsync>d__10.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 77
[2023-10-25T07:29:12.646Z] ---> (Inner Exception #0) System.ArgumentNullException: Value cannot be null.
[2023-10-25T07:29:12.647Z] Parameter name: encoding
[2023-10-25T07:29:12.648Z]    at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen)
[2023-10-25T07:29:12.648Z]    at Microsoft.Azure.Functions.Worker.Http.HttpRequestDataExtensions.<ReadAsStringAsync>d__0.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\Http\HttpRequestDataExtensions.cs:line 40
[2023-10-25T07:29:12.649Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.650Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.651Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.651Z]    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
[2023-10-25T07:29:12.652Z]    at Crm.WordToPdfConversion.FileConverter.<Run>d__2.MoveNext() in C:\Users\endi.zhupani\source\repos\Ximea.Services\src\legacy\Crm.WordToPdfConversion\FileConverter.cs:line 33<---
[2023-10-25T07:29:12.653Z]
Stack:    at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
[2023-10-25T07:29:12.654Z]    at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker`2.<>c.<InvokeAsync>b__6_0(Task`1 t) in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionInvoker.cs:line 32
[2023-10-25T07:29:12.655Z]    at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
[2023-10-25T07:29:12.655Z]    at System.Threading.Tasks.Task.Execute()
[2023-10-25T07:29:12.656Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.657Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.658Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.658Z]    at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.<ExecuteAsync>d__4.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 45
[2023-10-25T07:29:12.656Z] Executed 'Functions.worftopdfconversion' (Failed, Id=acb921dc-68d5-4cf5-8cb6-aebcbe133f11, Duration=4924ms)
[2023-10-25T07:29:12.659Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.660Z] System.Private.CoreLib: Exception while executing function: Functions.worftopdfconversion. System.Private.CoreLib: Result: Failure
Exception: System.AggregateException: One or more errors occurred. ---> System.ArgumentNullException: Value cannot be null.
[2023-10-25T07:29:12.661Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.662Z] Parameter name: encoding
[2023-10-25T07:29:12.662Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.663Z]    at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen)
[2023-10-25T07:29:12.664Z]    at Microsoft.Azure.Functions.Worker.Http.HttpRequestDataExtensions.<ReadAsStringAsync>d__0.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\Http\HttpRequestDataExtensions.cs:line 40
[2023-10-25T07:29:12.664Z]    at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.<Invoke>d__0.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 15
[2023-10-25T07:29:12.665Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.666Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.666Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.667Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.668Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.669Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.669Z]    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
[2023-10-25T07:29:12.670Z]    at Microsoft.Azure.Functions.Worker.FunctionsApplication.<InvokeFunctionAsync>d__10.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 77.
[2023-10-25T07:29:12.671Z]    at Crm.WordToPdfConversion.FileConverter.<Run>d__2.MoveNext() in C:\Users\endi.zhupani\source\repos\Ximea.Services\src\legacy\Crm.WordToPdfConversion\FileConverter.cs:line 33
[2023-10-25T07:29:12.672Z]    --- End of inner exception stack trace ---
[2023-10-25T07:29:12.673Z]    at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
[2023-10-25T07:29:12.673Z]    at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker`2.<>c.<InvokeAsync>b__6_0(Task`1 t) in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionInvoker.cs:line 32
[2023-10-25T07:29:12.674Z]    at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
[2023-10-25T07:29:12.675Z]    at System.Threading.Tasks.Task.Execute()
[2023-10-25T07:29:12.676Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.676Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.677Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.678Z]    at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.<ExecuteAsync>d__4.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 45
[2023-10-25T07:29:12.679Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.679Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.680Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.681Z]    at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.<Invoke>d__0.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 15
[2023-10-25T07:29:12.681Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.682Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.683Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.684Z]    at Microsoft.Azure.Functions.Worker.FunctionsApplication.<InvokeFunctionAsync>d__10.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 85
[2023-10-25T07:29:12.685Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.686Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.686Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.687Z]    at Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.<InvokeAsync>d__8.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Grpc\Handlers\InvocationHandler.cs:line 90
[2023-10-25T07:29:12.688Z] ---> (Inner Exception #0) System.ArgumentNullException: Value cannot be null.
[2023-10-25T07:29:12.688Z] Parameter name: encoding
[2023-10-25T07:29:12.689Z]    at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen)
[2023-10-25T07:29:12.690Z]    at Microsoft.Azure.Functions.Worker.Http.HttpRequestDataExtensions.<ReadAsStringAsync>d__0.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\Http\HttpRequestDataExtensions.cs:line 40
[2023-10-25T07:29:12.691Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.692Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.693Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.693Z]    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
[2023-10-25T07:29:12.694Z]    at Crm.WordToPdfConversion.FileConverter.<Run>d__2.MoveNext() in C:\Users\endi.zhupani\source\repos\Ximea.Services\src\legacy\Crm.WordToPdfConversion\FileConverter.cs:line 33<---
[2023-10-25T07:29:12.695Z]
Stack:    at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
[2023-10-25T07:29:12.695Z]    at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker`2.<>c.<InvokeAsync>b__6_0(Task`1 t) in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionInvoker.cs:line 32
[2023-10-25T07:29:12.696Z]    at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
[2023-10-25T07:29:12.697Z]    at System.Threading.Tasks.Task.Execute()
[2023-10-25T07:29:12.697Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.698Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.699Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.700Z]    at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.<ExecuteAsync>d__4.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 45
[2023-10-25T07:29:12.701Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.701Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.702Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.703Z]    at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.<Invoke>d__0.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 15
[2023-10-25T07:29:12.703Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.704Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.705Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.706Z]    at Microsoft.Azure.Functions.Worker.FunctionsApplication.<InvokeFunctionAsync>d__10.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 85
[2023-10-25T07:29:12.707Z] --- End of stack trace from previous location where exception was thrown ---
[2023-10-25T07:29:12.707Z]    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
[2023-10-25T07:29:12.708Z]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
[2023-10-25T07:29:12.709Z]    at Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.<InvokeAsync>d__8.MoveNext() in D:\a\_work\1\s\src\DotNetWorker.Grpc\Handlers\InvocationHandler.cs:line 90.

Function Code:

using Aspose.Words;
using Aspose.Words.Fonts;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Web.Helpers;

namespace Crm.WordToPdfConversion
{
    public class FileConverter
    {
        private readonly ILogger _logger;

        public FileConverter(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<FileConverter>();
        }

        [Function("wordtopdfconversion")]
        public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestData req)
        {
            _logger.LogInformation("wordtopdfconversion: C# HTTP trigger function processed a request.");

            string base64 = req.Query["doc"];

            if (base64 == null)
            {
                // Get request body
                var data = Json.Decode(await req.ReadAsStringAsync().ConfigureAwait(false));
                base64 = data?.base64;
            }
            if (base64 != null)
            {
                License l = new License();
                l.SetLicense(@"Aspose.Words.lic");
                if (!l.IsLicensed)
                {
                    throw new InvalidOperationException("License has expired for PDF conversion.");
                }

                MemoryStream input = new MemoryStream(Convert.FromBase64String(base64));
                input.Flush();
                input.Seek(0, SeekOrigin.Begin);

                MemoryStream output = new MemoryStream();
                MemoryFontSource font = new MemoryFontSource(Convert.FromBase64String(Base64Font));
                FontSourceBase[] fonts = { font };
                Document doc = new Document(input);
                FontSettings.DefaultInstance.SetFontsSources(fonts);
                doc.Save(output, SaveFormat.Pdf);
                output.Flush();
                output.Seek(0, SeekOrigin.Begin);

                base64 = Convert.ToBase64String(output.ToArray());
                input.Dispose();
                output.Dispose();
            }
            if (base64 == null)
            {
                var response = req.CreateResponse(HttpStatusCode.BadRequest);
                response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
                response.WriteString("Please pass data on the query string or in the request body");
                return response;
            }
            else
            {
                var response = req.CreateResponse(HttpStatusCode.OK);
                response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
                response.WriteString(base64);
                return response;
            }
        }

        private const string Base64Font = "base64string";
    }
}
fabiocav commented 1 year ago

Just for further info, the target framework for my functions project is net48, so I'm using .NET Framework.

@endizhupani thank you for sharing this. It could potentially be something specific to .NET Framework, but @kshyju is correct and I would expect the behavior here to be consistent with the behavior exposed by the StreamReader constructor we use.

The only scenario I'd expect the behavior you're seeing is if the stream is using an encoding that couldn't be inferred by the StreamReader

endizhupani commented 1 year ago

@fabiocav I dug a bit deeper into this. Looking at the stack trace it seems like the NRE is being thrown from directly inside the StreamReader constructor. Does it look at the stream to infer the encoding already while being constructed?

Looking at the dependencies of DotNetWorker.Core, it seems to have net5.0 and netstandard2.0. I'm a bit unclear on this: do they have the same implementation of StreamReader, or each its own? Screenshot 2023-10-26 142209

I had a look at the source code of the StreamReader constructor in net5.0 and I don't see any logic there which infers the encoding. I also saw the following at the beginning of the constructors body:

if (encoding == null)
{
    encoding = Encoding.UTF8;
}

So the NRE should not be thrown.

Since my function app runs on .NET Framework, I'm assuming that the implementation used is the one from netstandard2.0. I can't look at the source code but could it be that this implementation actually does not allow null? Looking at the signature from the screenshot above, the Encoding param is not market as nullable for the netstandard version.

kshyju commented 1 year ago

Thanks @endizhupani Yes, you are correct, in .netframework, the StreamReader constructor throws when encoding parameter is null. In net6+, it sets the default value UTF8) if the parameter value is null.

https://github.com/dotnet/runtime/blob/e7b8488daf32c7a607632ec4be605ba3ccf171a7/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs#L143-L146

I will take a look at your PR with the fix. Thank you for reporting the issue and opening a PR to fix it.

fabiocav commented 1 year ago

Indeed. We'll continue to iterate on the PR, but the changes are reasonable.