Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.Text.Json.JsonSerializer fails to parse literals on Linux ARM 32 bits #21741

Open
rodrigovaras opened this issue Jan 27, 2024 · 1 comment

Comments

@rodrigovaras
Copy link

rodrigovaras commented Jan 27, 2024

We have an app that use System.Text.Json.JsonSerializer version="8.0.0"
Found out the app when running on linux-arm mono (Debian 12) mono 6.2.x it fails to parse a simple JSON buffer.

It seems that when the JSON has valid literals it will throw an exception like this:
Unhandled exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Text.Json.JsonException: 'null}' is an invalid JSON literal. Expected the literal 'null'

The problem does not reveal on Mono Debian 16 on linux-x64 box (on a VM), Windows version also runs fine.

This is blocking us at this point since the whole point of using Mono was to deal with 32 bits architectures not supported by .NET 8.

Steps to Reproduce

internal sealed class Simple
{
public T? Property { get; set; }
}

const string nulljson = @"{""Property"": null}";
var simple = JsonSerializer.Deserialize<Simple>(nulljson);
System.Console.WriteLine($"Simple string value:{simple!.Property}");

Our project to repro:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>net8.0;net47</TargetFrameworks>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
	  <LangVersion>latest</LangVersion>
  </PropertyGroup>
	<ItemGroup Condition="'$(TargetFramework)' != 'net8.0'">
		<PackageReference Include="System.Text.Json" Version="8.0.0"/>
	</ItemGroup>
</Project>
.```

## On which platforms did you notice this

[ ] macOS
[x ] Linux ARM (32 bits)
[ ] Windows

**Version Used**:
root@tsimx28:/home/user/mono-test# mono --version

Mono JIT compiler version 6.12.0.200 (tarball Tue Jul 11 21:44:32 UTC 2023)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
.TLS:           __thread
.SIGSEGV:       normal
.Notifications: epoll
.Architecture:  armel,vfp+fallback
.Disabled:      none
.Misc:          softdebug 
.Interpreter:   yes
.LLVM:          supported, not enabled.
.Suspend:       preemptive
.GC:            sgen (concurrent by default)


## Stacktrace
�[6n�[H�[Ji%p1%d;%p2%drUnhandled exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Text.Json.JsonException: 'null}' is an invalid JSON literal. Expected the literal 'null'. Path: $.Property | LineNumber: 0 | BytePositionInLine: 13. ---> System.Text.Json.JsonReaderException: 'null}' is an invalid JSON literal. Expected the literal 'null'. LineNumber: 0 | BytePositionInLine: 13.
  at System.Text.Json.ThrowHelper.ThrowJsonReaderException (System.Text.Json.Utf8JsonReader& json, System.Text.Json.ExceptionResource resource, System.Byte nextByte, System.ReadOnlySpan`1[T] bytes) [0x00009] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Utf8JsonReader.ThrowInvalidLiteral (System.ReadOnlySpan`1[T] span) [0x00020] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Utf8JsonReader.CheckLiteral (System.ReadOnlySpan`1[T] span, System.ReadOnlySpan`1[T] literal) [0x00065] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Utf8JsonReader.ConsumeLiteral (System.ReadOnlySpan`1[T] literal, System.Text.Json.JsonTokenType tokenType) [0x0001b] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Utf8JsonReader.ConsumeValue (System.Byte marker) [0x00078] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Utf8JsonReader.ReadSingleSegment () [0x00123] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Utf8JsonReader.Read () [0x00008] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.JsonHelpers.ReadWithVerify (System.Text.Json.Utf8JsonReader& reader) [0x00000] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[T].ReadPropertyValue (System.Object obj, System.Text.Json.ReadStack& state, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.Serialization.Metadata.JsonPropertyInfo jsonPropertyInfo, System.Boolean useExtensionProperty) [0x00011] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[T].PopulatePropertiesFastPath (System.Object obj, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& state) [0x00047] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[T].OnTryRead (System.Text.Json.Utf8JsonReader& reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options, System.Text.Json.ReadStack& state, T& value) [0x00083] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Serialization.JsonConverter`1[T].TryRead (System.Text.Json.Utf8JsonReader& reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options, System.Text.Json.ReadStack& state, T& value, System.Boolean& isPopulatedValue) [0x00184] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Serialization.JsonConverter`1[T].ReadCore (System.Text.Json.Utf8JsonReader& reader, System.Text.Json.JsonSerializerOptions options, System.Text.Json.ReadStack& state) [0x000be] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
   --- End of inner exception stack trace ---
  at System.Text.Json.ThrowHelper.ReThrowWithPath (System.Text.Json.ReadStack& state, System.Text.Json.JsonReaderException ex) [0x0007c] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Serialization.JsonConverter`1[T].ReadCore (System.Text.Json.Utf8JsonReader& reader, System.Text.Json.JsonSerializerOptions options, System.Text.Json.ReadStack& state) [0x00107] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1[T].Deserialize (System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& state) [0x0000d] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.JsonSerializer.ReadFromSpan[TValue] (System.ReadOnlySpan`1[T] utf8Json, System.Text.Json.Serialization.Metadata.JsonTypeInfo`1[T] jsonTypeInfo, System.Nullable`1[T] actualByteCount) [0x0002d] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
  at System.Text.Json.JsonSerializer.Deserialize[TValue] (System.ReadOnlySpan`1[T] utf8Json, System.Text.Json.JsonSerializerOptions options) [0x00007] in <03a2e6e98fe34439ab6c9fe805d43486>:0 
@rodrigovaras
Copy link
Author

Here is the offending source code on dotnet/runtime repo:
$\src\libraries\System.Text.Json\src\System\Text\Json\Reader\Utf8JsonReader.cs

    // Consumes 'null', or 'true', or 'false'
    private bool ConsumeLiteral(ReadOnlySpan<byte> literal, JsonTokenType tokenType)
    {
        ReadOnlySpan<byte> span = _buffer.Slice(_consumed);
        Debug.Assert(span.Length > 0);
        Debug.Assert(span[0] == 'n' || span[0] == 't' || span[0] == 'f');

        if (!span.StartsWith(literal)) **<------ this return false when in normal scenario should be true**
        {
            return CheckLiteral(span, literal);
        }

        ValueSpan = span.Slice(0, literal.Length);
        _tokenType = tokenType;
        _consumed += literal.Length;
        _bytePositionInLine += literal.Length;
        return true;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant