Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Avoid StackOverflowException when cyclic Type reference#37818

Merged
steveharter merged 2 commits intodotnet:masterfrom
steveharter:AvoidStackOverflowOnCyclicTypes
May 21, 2019
Merged

Avoid StackOverflowException when cyclic Type reference#37818
steveharter merged 2 commits intodotnet:masterfrom
steveharter:AvoidStackOverflowOnCyclicTypes

Conversation

@steveharter
Copy link
Copy Markdown
Contributor

Fixes https://github.com/dotnet/corefx/issues/37313

This is fixed by lazy evaluating the ElementClassInfo property so we don't end up in a recursive loop. To do this, the JsonPropertyInfo now holds a reference to the options class which it uses during lazy evaluation; when the code was originally written this was not possible since an instance of JsonPropertyInfo was not linked with the options instance.

Also removed a // todo: to minimize hashtable lookups, cache JsonClassInfo: by leveraging the same lazy evaluation approach (also not possible before). This has a minor perf gain for lists and dictionaries.


public class TestClassWithArrayOfElementsOfTheSameClass
{
public TestClassWithArrayOfElementsOfTheSameClass[] Array { get; set; }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a couple more tests for different collection types, like List<T> and Dictionary, along with one where the recursive property is deeper within a .NET object graph?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Adding a more complex test.

//It shouldn't throw when there is no real cycle reference, and just empty object is created
string json = JsonSerializer.ToString(obj);
Assert.Equal(@"{}", json);
Assert.Equal(@"{""Array"":null}", json);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rynowak previously suggested that this return an empty object (i.e. {}):
#37611 (comment)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The array is null, so it has a null value like every other null property.

_elementClassInfo = Options.GetOrAddClass(_elementType);
}

return _elementClassInfo;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it OK for this to still return null sometimes?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Other code uses it to determine if the current property can contain elements. I'll add a comment\doc.

@steveharter steveharter merged commit 857d1d1 into dotnet:master May 21, 2019
@steveharter
Copy link
Copy Markdown
Contributor Author

Committing this; test failures due to System.Drawing.Common.Tests

@steveharter steveharter deleted the AvoidStackOverflowOnCyclicTypes branch May 21, 2019 18:51
@karelz karelz added this to the 3.0 milestone May 22, 2019
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[System.Text.Json]: Recursive property in collection type results in stackoverflow

4 participants