From 9c769a612374a7719985aa346add5a0a3ebb1655 Mon Sep 17 00:00:00 2001 From: Adeel Date: Sun, 10 May 2020 05:47:24 +0300 Subject: [PATCH] Disallow usage of alias before anchor declaration --- .../Serialization/SerializationTests.cs | 122 +++++++----------- .../AliasValueDeserializer.cs | 3 +- 2 files changed, 45 insertions(+), 80 deletions(-) diff --git a/YamlDotNet.Test/Serialization/SerializationTests.cs b/YamlDotNet.Test/Serialization/SerializationTests.cs index 823c841a4..06648e950 100644 --- a/YamlDotNet.Test/Serialization/SerializationTests.cs +++ b/YamlDotNet.Test/Serialization/SerializationTests.cs @@ -233,19 +233,6 @@ public void DeserializeConvertible() result.aaa.Should().Be("[hello, world]"); } - [Fact] - public void DeserializationOfObjectsHandlesForwardReferences() - { - var text = Lines( - "Nothing: *forward", - "MyString: &forward ForwardReference"); - - var result = Deserializer.Deserialize(UsingReaderFor(text)); - - result.ShouldBeEquivalentTo( - new { Nothing = "ForwardReference", MyString = "ForwardReference" }, o => o.ExcludingMissingMembers()); - } - [Fact] public void DeserializationFailsForUndefinedForwardReferences() { @@ -511,30 +498,6 @@ public void DeserializeExplicitList() .Subject.As>().Should().Equal(3, 4, 5); } - [Fact] - public void DeserializationOfGenericListsHandlesForwardReferences() - { - var text = Lines( - "- *forward", - "- &forward ForwardReference"); - - var result = Deserializer.Deserialize(UsingReaderFor(text)); - - result.Should().Equal(new[] { "ForwardReference", "ForwardReference" }); - } - - [Fact] - public void DeserializationOfNonGenericListsHandlesForwardReferences() - { - var text = Lines( - "- *forward", - "- &forward ForwardReference"); - - var result = Deserializer.Deserialize(UsingReaderFor(text)); - - result.Should().Equal(new[] { "ForwardReference", "ForwardReference" }); - } - [Fact] public void RoundtripList() { @@ -612,47 +575,6 @@ public void RoundtripDictionary() result.Should().Equal(obj); } - [Fact] - public void DeserializationOfGenericDictionariesHandlesForwardReferences() - { - var text = Lines( - "key1: *forward", - "*forwardKey: ForwardKeyValue", - "*forward: *forward", - "key2: &forward ForwardReference", - "key3: &forwardKey key4"); - - var result = Deserializer.Deserialize>(UsingReaderFor(text)); - - result.Should().Equal(new Dictionary { - { "ForwardReference", "ForwardReference" }, - { "key1", "ForwardReference" }, - { "key2", "ForwardReference" }, - { "key4", "ForwardKeyValue" }, - { "key3", "key4" } - }); - } - - [Fact] - public void DeserializationOfNonGenericDictionariesHandlesForwardReferences() - { - var text = Lines( - "key1: *forward", - "*forwardKey: ForwardKeyValue", - "*forward: *forward", - "key2: &forward ForwardReference", - "key3: &forwardKey key4"); - - var result = Deserializer.Deserialize(UsingReaderFor(text)); - - result.Should().BeEquivalentTo( - Entry("ForwardReference", "ForwardReference"), - Entry("key1", "ForwardReference"), - Entry("key2", "ForwardReference"), - Entry("key4", "ForwardKeyValue"), - Entry("key3", "key4")); - } - [Fact] public void DeserializeListOfDictionaries() { @@ -1562,6 +1484,38 @@ public void DeserializationOfStreamWithDuplicateAnchorsSucceeds() Assert.NotNull(deserialized); } + private sealed class AnchorPrecedence + { + internal sealed class AnchorPrecedenceNested + { + public string b1 { get; set; } + public Dictionary b2 { get; set; } + } + + public string a { get; set; } + public AnchorPrecedenceNested b { get; set; } + public string c { get; set; } + } + + [Fact] + public void DeserializationWithDuplicateAnchorsSucceeds() + { + var sut = new Deserializer(); + var deserialized = sut.Deserialize(Yaml.ReaderForText(@" +a: &anchor1 test0 +b: + b1: &anchor1 test1 + b2: + b21: &anchor1 test2 +c: *anchor1")); + + Assert.Equal(@"test0", deserialized.a); + Assert.Equal("test1", deserialized.b.b1); + Assert.Contains(@"b21", deserialized.b.b2.Keys); + Assert.Equal(@"test2", deserialized.b.b2["b21"]); + Assert.Equal(@"test2", deserialized.c); + } + [Fact] public void SerializeExceptionWithStackTrace() { @@ -1789,6 +1743,18 @@ public void AnchorNameWithTrailingColonReferencedInKeyCanBeDeserialized() Assert.Equal(@"anchor "" value """, deserialized["myvalue"]); } + [Fact] + public void AliasBeforeAnchorCannotBeDeserialized() + { + var sut = new Deserializer(); + Action action = () => sut.Deserialize>(Yaml.ReaderForText(@" +a: *anchor1 +b: &anchor1 test0 +c: *anchor1")); + + action.ShouldThrow(); + } + [Fact] public void AnchorWithAllowedCharactersCanBeDeserialized() { diff --git a/YamlDotNet/Serialization/ValueDeserializers/AliasValueDeserializer.cs b/YamlDotNet/Serialization/ValueDeserializers/AliasValueDeserializer.cs index 5cdfab3af..07b619bd1 100644 --- a/YamlDotNet/Serialization/ValueDeserializers/AliasValueDeserializer.cs +++ b/YamlDotNet/Serialization/ValueDeserializers/AliasValueDeserializer.cs @@ -104,8 +104,7 @@ public ValuePromise(object? value) var aliasState = state.Get(); if (!aliasState.TryGetValue(alias.Value, out var valuePromise)) { - valuePromise = new ValuePromise(alias); - aliasState.Add(alias.Value, valuePromise); + throw new AnchorNotFoundException(alias.Start, alias.End, $"Alias ${alias.Value} cannot precede anchor declaration"); } return valuePromise.HasValue ? valuePromise.Value : valuePromise;