dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.55k stars 10.05k forks source link

NewtonsoftJsonInputFormatter will fail deserializing stream with byte order mark #53315

Open jeppevammenkristensen opened 10 months ago

jeppevammenkristensen commented 10 months ago

Is there an existing issue for this?

Describe the bug

The NewtonsoftJsonInputFormatter will fail to deserialize a stream that has a byte order mark in the start of it, but the default SystemTextJsonInputFormatter will handle deserializing the stream without throwing an exception. Also an asp.net solution using the .net framework would also handle it.

Expected Behavior

I expect the NewtonsoftJsonInputFormatter to handle and deserialize a json stream where a byteordermark has been added without throwing an exception. Like how SystemTextJsonInputFormatter does it.

Steps To Reproduce

I have created a repo in github where the error can be reproduced. It consists of a WebApi project that has included the Microsoft.AspNetCore.Mvc.NewtonsoftJson package and enabled newtonsoft as the formatter. It also has a Test project (console) that will call the given api with data serialized in a way that produces the error.

Exceptions (if any)

The following is from the asp.net core project where the error occurs for a json stream that is using utf8 (and has a Byte Order Mark) in the start of the stream.

dbug: Microsoft.AspNetCore.Mvc.Formatters.NewtonsoftJsonInputFormatter[1]
      JSON input formatter threw an exception.
      Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: ?. Path '', line 0, position 0.
         at Newtonsoft.Json.JsonTextReader.ParseValue()
         at Newtonsoft.Json.JsonTextReader.Read()
         at Newtonsoft.Json.JsonReader.ReadAndMoveToContent()
         at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
         at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)

The deserialization is invoked here

Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs:line 161 in the ReadRequestBodyAsync method

try
{
    model = jsonSerializer.Deserialize(jsonReader, type);
}
finally
{
    // Clean up the error handler since CreateJsonSerializer() pools instances.
    jsonSerializer.Error -= ErrorHandler;
    ReleaseJsonSerializer(jsonSerializer);

    if (disposeReadStream)
    {
        await readStream.DisposeAsync();
    }
}

.NET Version

6.0 and above (might also effect earlier versions)

Anything else?

jeppevammenkristensen commented 9 months ago

/azp run