Skip to content

Unexpected behaviour during substitution chain #390

@g-jozsef

Description

@g-jozsef

Version Information
Version of Akka.NET? N/A (using it standalone)
Which Akka.NET Modules? N/A

Describe the bug
When having a transitive substitution with no changed values (observed behavior) HOCON throws a cyclic reference exception.

To Reproduce
using 2.0.4 from nuget:

using System;
using Hocon;
					
public class Program
{
	public static void Main()
	{
		var c = @"
        default {
            some-variable = ""some-value""
        }

        data = ${default} {
            some-variable = ""some-value2""
        }

        item = ${data} {
        }";
		Console.WriteLine("loading... " + c);
		Console.WriteLine("loaded: \n" + HoconConfigurationFactory.ParseString(c).PrettyPrint(2));
	}
}

correctly prints

loaded: 
{
  default : {
    some-variable : "some-value"
  },
  data : {
    some-variable : "some-value2"
  },
  item : {
    some-variable : "some-value2"
  }
}

but

using System;
using Hocon;
					
public class Program
{
	public static void Main()
	{
		var c = @"
	default {
            some-variable = ""some-value""
        }

        data = ${default} {
            some-variable = ""some-value""
        }

        item = ${data} {
        }";
		Console.WriteLine("loading... " + c);
		Console.WriteLine("loaded: \n" + HoconConfigurationFactory.ParseString(c).PrettyPrint(2));
	}
}

throws

Unhandled exception. Hocon.HoconParserException: Invalid substitution declaration. A cyclic substitution loop is detected in the Hocon file.. At path 'data', line 9, position 20.
 ---> Hocon.HoconException: A cyclic substitution loop is detected in the Hocon file.
   at Hocon.HoconParser.ResolveSubstitution(HoconSubstitution sub)
   at Hocon.HoconParser.ResolveSubstitutions()
   --- End of inner exception stack trace ---
   at Hocon.HoconParser.ResolveSubstitutions()
   at Hocon.HoconParser.ParseText(String text, Boolean resolveSubstitutions, HoconIncludeCallbackAsync includeCallback)
   at Hocon.HoconParser.Parse(String text, HoconIncludeCallbackAsync includeCallback)
   at Hocon.HoconConfigurationFactory.ParseString(String hocon, HoconIncludeCallbackAsync includeCallback)
   at Hocon.HoconConfigurationFactory.ParseString(String hocon)
   at Program.Main()

Please NOTE:
Only difference between the two is this line:

        data = ${default} {
+            some-variable = ""some-value""
-            some-variable = ""some-value2""
        }

Expected behavior
I expected item's some-variable to inherit "some-value". OR both cases should throw if transitive substitution is not allowed.

  item : {
    some-variable : "some-value"
  }

Actual behavior
A cyclic substitution loop is detected when there isn't one.

Screenshots
N/A

Environment
Issue detected in my large project on Windows, using dotnet 7.0.102.
I wrote this example on https://dotnetfiddle.net/ using .NET 7 but the issue reproduces in other dotnet versions as well (and of course in a larger scale in my project... it took a while to pinpoint to this minimal reproducible version :) )

Additional context
N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions