StackOverflowException in JsonConvert.DeserializeXmlNode

We recently upgraded to Json.NET 10.0r2 from 6.0.1, and since the upgrade, I've noticed that one of our unit tests is throwing an exception when trying to deserialize an invalid Json. The goal of the test was to ensure that invalid Json is handled. This same test was used to throw a JsonSerializationException, but now it flushes nUnit using StackOverflow.

I have reproduced it in my own Json.NET unit test with this test:

[Test]
public void FailOnInvalidJSON( )
{
    string json = @"{'Row' : ";

    Assert.Throws<JsonSerializationException>(()=>JsonConvert.DeserializeXmlNode(json, "ROOT"));
}

      

Any ideas for working around?

Thank!

+3


source to share


1 answer


Update

And quickly fixed in the changeset 822c3f0

. Should be in the next release after 10.0.2.

Original Answer

Seems like a change JsonTextReader

in 8.0.1, may have encountered a bug in XmlNodeConverter

.

In 7.0.1 , when an unexpected end of file is reached, JsonReader.TokenType

it becomes JsonToken.None

after the next try Read()

, which causes an DeserializeNode()

exception to be thrown Unexpected JsonToken when deserializing node: None

. But in 8.0.1 and then TokenType

it seems to remain in the type of the last token encountered, namely JsonToken.PropertyName

that one that causes infinite recursion.

The correct fix would be XmlNodeConverter.DeserializeNode()

around line 2171 to check the return from reader.Read()

:



case JsonToken.PropertyName:
    if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null)
    {
        throw JsonSerializationException.Create(reader, "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName.");
    }

    string propertyName = reader.Value.ToString();
    // Need to check the return from reader.Read() here:
    if (!reader.Read())
    {
        throw JsonSerializationException.Create(reader, "Unexpected end of file when deserializing property: " + propertyName );
    }

      

... And there seems to be a few more places in XmlNodeConverter.cs

where the return from needs to be checked reader.Read()

, for example ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)

around line 1942 .

You can report a problem if you like.

In the meantime, your options for a workaround would be as follows:

  • Corrupt JSON in a different way, for example:

    string json = @"{'Row' : }";
    
          

    And check out the more general exception JsonException

    .

  • Pre-parse the JSON into JToken

    :

    Assert.Throws<JsonException>(()=>JsonConvert.DeserializeXmlNode(JToken.Parse(json).ToString(), "ROOT"));
    
          

+1


source







All Articles