haplokuon / netDxf

.net dxf Reader-Writer
MIT License
966 stars 393 forks source link

StackOverFlowException on exploding blocks #465

Closed Asura336 closed 9 months ago

Asura336 commented 1 year ago

A StackOverFlowException will be thrown when exploding a Block in ModelSpace (at version 2.4.2 and 3.0.0), exception message like:

   at netDxf.XData.Clone()
   at netDxf.Tables.ApplicationRegistry.Clone(System.String)
   at netDxf.XData.Clone()
   at netDxf.Tables.ApplicationRegistry.Clone(System.String)
   at netDxf.XData.Clone()
   at netDxf.Tables.ApplicationRegistry.Clone(System.String)
   at netDxf.XData.Clone()
   at netDxf.Entities.Line.Clone()
   at netDxf.Entities.Insert.Explode()
   at Program.<Main>$(System.String[])

There is the sample code and dxf file that will raise exception. block-stackoverflow-case.zip

using netDxf;
using netDxf.Entities;
using System.Text;

if (args.Length != 0)
{
    string src = args[0]; // dxf file path from args
    if (File.Exists(src) && src.EndsWith(".dxf", StringComparison.OrdinalIgnoreCase))
    {
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        DxfDocument doc = DxfDocument.Load(src)
            ?? throw new NullReferenceException();

        string activeLayout = doc.Entities.ActiveLayout;
        var associatedBlock = doc.Layouts[activeLayout].AssociatedBlock;
        var docEntities = associatedBlock.Entities;

        List<EntityObject> entities = new List<EntityObject>();
        int count = docEntities.Count;
        for (int i = 0; i < count; i++)
        {
            var item = docEntities[i];
            switch (item)
            {
                case Insert insert:
                    entities.AddRange(insert.Explode());  // here
                    break;
                default:
                    // other...
                    entities.Add(item);
                    break;
            }
        }
        //...
    }
}
haplokuon commented 1 year ago

I have uploaded a fix for this problem. This problem appears when cloning the extended data associated to an application registry with circular references, the code ended in an infinite loop and in a StackOverFlow exception. This is a very uncommon case that I have never seen before, if you use AutoCad it seems that it was created by some short of plugin for it, all the application registries that had this problem started with the prefix GENIUS.