Description
Describe the bug
When CsvHelper tries to auto map a type that references itself, it can run into a stack overflow. This happens only under certail conditions. The self referential property needs to be declared after another property that requires mapping.
To Reproduce
using System.Globalization;
using CsvHelper;
public class MyTypedId
{
public Guid Value { get; set; }
}
public sealed class MyClass
{
public MyTypedId Id { get; set; }
public MyClass Parent { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
var buffer = new BufferedStream(new MemoryStream());
var csvWriter = new CsvWriter(new StreamWriter(buffer), CultureInfo.InvariantCulture);
var context = new CsvContext(csvWriter);
var type = typeof(MyClass);
context.AutoMap(type);
}
}
Changing MyClass
in the above example to either of the following does not produce a stack overflow:
public sealed class MyClass
{
public MyClass Parent { get; set; }
public MyTypedId Id { get; set; }
}
public sealed class MyClass
{
public Guid Id { get; set; }
public MyClass Parent { get; set; }
}
Expected behavior
Creating a class map should not result in a stack overflow. It should detect the recursion an stop, or throw an exception.
Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
I already started looking into what could be the causes of this. ClassMap.cs line 403 looks like the likely culprit to me. During mapping of the example provided, mapParents
contains two entries for MyClass
. One for the type being mapped, the other for the property. When the Id
property gets evaluated, mapParents.Find(type)
returns the first node. mapParents.Drop
then drops both entries, though in this case it should only drop the second node. This explains why no stack overflow occurs when the proprties in MyClass
are flipped.
Either changing Find
to FindLast
or keeping a reference to the node from when it was added fixes the issue. I can however not tell wheter this has implications on some other use case. If i get the time during the weekend I would fix this myself.