From d155cf9bc3d15e331b9a3eb3b2869c36e32c2059 Mon Sep 17 00:00:00 2001 From: Tomer Amir Date: Sun, 28 May 2023 15:51:59 +0300 Subject: [PATCH 1/3] Fix infinite recursion of the hash code function of YamlMappingNode --- YamlDotNet/RepresentationModel/YamlMappingNode.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YamlDotNet/RepresentationModel/YamlMappingNode.cs b/YamlDotNet/RepresentationModel/YamlMappingNode.cs index 3aa34d9a..49d793f6 100644 --- a/YamlDotNet/RepresentationModel/YamlMappingNode.cs +++ b/YamlDotNet/RepresentationModel/YamlMappingNode.cs @@ -297,7 +297,7 @@ public override int GetHashCode() foreach (var entry in children) { hashCode = CombineHashCodes(hashCode, entry.Key); - hashCode = CombineHashCodes(hashCode, entry.Value); + hashCode = CombineHashCodes(hashCode, entry.Value.Start); } return hashCode; } From 2c57ca2bc4472da4611639be9c49845b80ec53d9 Mon Sep 17 00:00:00 2001 From: barapiiro Date: Tue, 28 May 2024 15:52:05 +0300 Subject: [PATCH 2/3] fix hashcode recursion only for the recursive case (anchor) --- YamlDotNet/RepresentationModel/YamlMappingNode.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/YamlDotNet/RepresentationModel/YamlMappingNode.cs b/YamlDotNet/RepresentationModel/YamlMappingNode.cs index 49d793f6..b356f88c 100644 --- a/YamlDotNet/RepresentationModel/YamlMappingNode.cs +++ b/YamlDotNet/RepresentationModel/YamlMappingNode.cs @@ -297,7 +297,9 @@ public override int GetHashCode() foreach (var entry in children) { hashCode = CombineHashCodes(hashCode, entry.Key); - hashCode = CombineHashCodes(hashCode, entry.Value.Start); + hashCode = entry.Value.Anchor.IsEmpty + ? CombineHashCodes(hashCode, entry.Value) + : CombineHashCodes(hashCode, entry.Value.Anchor); } return hashCode; } From cc5f5a6b7af76980b17e7e44d868973c7d5f531b Mon Sep 17 00:00:00 2001 From: barapiiro Date: Tue, 28 May 2024 15:52:57 +0300 Subject: [PATCH 3/3] adding test cases that cause recursive GetHashCode recursive call --- .../RepresentationModel/YamlStreamTests.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/YamlDotNet.Test/RepresentationModel/YamlStreamTests.cs b/YamlDotNet.Test/RepresentationModel/YamlStreamTests.cs index d06ec33c..9a5d9379 100644 --- a/YamlDotNet.Test/RepresentationModel/YamlStreamTests.cs +++ b/YamlDotNet.Test/RepresentationModel/YamlStreamTests.cs @@ -45,22 +45,26 @@ public void LoadSimpleDocument() Assert.Equal(YamlNodeType.Scalar, stream.Documents[0].RootNode.NodeType); } - [Fact] - public void AccessingAllNodesOnInfinitelyRecursiveDocumentThrows() + [Theory] + [InlineData("&a [*a]")] + [InlineData("?\n key: &id1\n recursion: *id1\n: foo")] + public void AccessingAllNodesOnInfinitelyRecursiveDocumentThrows(string yaml) { var stream = new YamlStream(); - stream.Load(Yaml.ParserForText("&a [*a]")); + stream.Load(Yaml.ParserForText(yaml)); var accessAllNodes = new Action(() => stream.Documents.Single().AllNodes.ToList()); accessAllNodes.ShouldThrow("because the document is infinitely recursive."); } - [Fact] - public void InfinitelyRecursiveNodeToStringSucceeds() + [Theory] + [InlineData("&a [*a]")] + [InlineData("?\n key: &id1\n recursion: *id1\n: foo")] + public void InfinitelyRecursiveNodeToStringSucceeds(string yaml) { var stream = new YamlStream(); - stream.Load(Yaml.ParserForText("&a [*a]")); + stream.Load(Yaml.ParserForText(yaml)); var toString = stream.Documents.Single().RootNode.ToString();