From eed2603fd7a85e1486a088aaeb0ca6ec9d491a67 Mon Sep 17 00:00:00 2001 From: Adora Lynch Date: Fri, 9 May 2025 22:53:07 -0400 Subject: [PATCH 1/3] Add tests showing problematic meta-key exposure --- Tests/YamsTests/AnchorCodingTests.swift | 59 ++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/Tests/YamsTests/AnchorCodingTests.swift b/Tests/YamsTests/AnchorCodingTests.swift index 47df167f..aa0bb98e 100644 --- a/Tests/YamsTests/AnchorCodingTests.swift +++ b/Tests/YamsTests/AnchorCodingTests.swift @@ -328,6 +328,61 @@ class AnchorAliasingTests: XCTestCase { """ ) } + func testMetaPropertyKeyExposure_anchors() throws { + let string = """ + &foo + x: 120 + + """ + + try _testMetaPropertyKeyExposure(source: string) + } + + func testMetaPropertyKeyExposure_tags() throws { + let string = """ + ! + x: 120 + + """ + + try _testMetaPropertyKeyExposure(source: string) + } + + func testMetaPropertyKeyExposure_tags_and_anchors() throws { + let string = """ + ! + &foo + x: 120 + + """ + try _testMetaPropertyKeyExposure(source: string) + } + + func _testMetaPropertyKeyExposure(source: String) throws { + struct S: Codable { + var x: Int + + init(x: Int) { + self.x = x + } + init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.x = try container.decode(Int.self, forKey: .x) + + XCTAssertEqual(container.allKeys.count, 1) + } + } + + let data = source.data(using: .utf8)! + + let s2 = try YAMLDecoder().decode(S.self, from: data) + XCTAssertEqual(s2.x, 120) + + let dict = try YAMLDecoder().decode([String: String].self, from: data) + XCTAssertEqual(dict["x"], "120") + XCTAssertEqual(dict.keys.count, 1) + } + /// A type used to contain values used during testing private struct SimplePair: Hashable, Codable { let first: First @@ -348,7 +403,7 @@ private protocol SimpleProtocol: Codable, Hashable { var intValue: IntegerValue { get } } -private struct SimpleWithAnchor: SimpleProtocol, YamlAnchorProviding { +private struct SimpleWithAnchor: SimpleProtocol, YamlAnchorCoding { let nested: NestedStruct let intValue: Int var yamlAnchor: Anchor? = "simple" @@ -375,7 +430,7 @@ private struct SimpleWithStringTypeAnchorName: SimpleProtocol { #if swift(>=6.0) extension Int: @retroactive RawRepresentable {} #else -extension Int: RawRepresentable {} +extension Int: @retroactive RawRepresentable {} #endif extension Int { public var rawValue: Int { self } From f62f9d5aabb76bfe068ffb68bd6e2dc57df5c93c Mon Sep 17 00:00:00 2001 From: Adora Lynch Date: Fri, 9 May 2025 23:02:01 -0400 Subject: [PATCH 2/3] Don't use @retroactive where not available --- Tests/YamsTests/AnchorCodingTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/YamsTests/AnchorCodingTests.swift b/Tests/YamsTests/AnchorCodingTests.swift index aa0bb98e..de15c926 100644 --- a/Tests/YamsTests/AnchorCodingTests.swift +++ b/Tests/YamsTests/AnchorCodingTests.swift @@ -430,7 +430,7 @@ private struct SimpleWithStringTypeAnchorName: SimpleProtocol { #if swift(>=6.0) extension Int: @retroactive RawRepresentable {} #else -extension Int: @retroactive RawRepresentable {} +extension Int: RawRepresentable {} #endif extension Int { public var rawValue: Int { self } From ba60d03c4442cc6cfb4fafd57df10197e92fb8fc Mon Sep 17 00:00:00 2001 From: Adora Lynch Date: Fri, 9 May 2025 23:22:54 -0400 Subject: [PATCH 3/3] Use two properties when testig for meta-keys --- Tests/YamsTests/AnchorCodingTests.swift | 50 ++++++++++++++----------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/Tests/YamsTests/AnchorCodingTests.swift b/Tests/YamsTests/AnchorCodingTests.swift index de15c926..c7c8d4c3 100644 --- a/Tests/YamsTests/AnchorCodingTests.swift +++ b/Tests/YamsTests/AnchorCodingTests.swift @@ -331,7 +331,8 @@ class AnchorAliasingTests: XCTestCase { func testMetaPropertyKeyExposure_anchors() throws { let string = """ &foo - x: 120 + someInt: 120 + someString: beep """ @@ -341,7 +342,8 @@ class AnchorAliasingTests: XCTestCase { func testMetaPropertyKeyExposure_tags() throws { let string = """ ! - x: 120 + someInt: 120 + someString: beep """ @@ -352,35 +354,39 @@ class AnchorAliasingTests: XCTestCase { let string = """ ! &foo - x: 120 + someInt: 120 + someString: beep """ try _testMetaPropertyKeyExposure(source: string) } - - func _testMetaPropertyKeyExposure(source: String) throws { - struct S: Codable { - var x: Int - - init(x: Int) { - self.x = x + + private func _testMetaPropertyKeyExposure(source: String) throws { + struct KeyCountAssertingStruct: Codable { + var someInt: Int + var someString: String + + init(someInt: Int, someString: String) { + self.someInt = someInt + self.someString = someString } init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - self.x = try container.decode(Int.self, forKey: .x) - - XCTAssertEqual(container.allKeys.count, 1) + self.someInt = try container.decode(Int.self, forKey: .someInt) + self.someString = try container.decode(String.self, forKey: .someString) + + XCTAssertEqual(container.allKeys.count, 2) } } - - let data = source.data(using: .utf8)! - - let s2 = try YAMLDecoder().decode(S.self, from: data) - XCTAssertEqual(s2.x, 120) - - let dict = try YAMLDecoder().decode([String: String].self, from: data) - XCTAssertEqual(dict["x"], "120") - XCTAssertEqual(dict.keys.count, 1) + + let decoded = try YAMLDecoder().decode(KeyCountAssertingStruct.self, from: source) + XCTAssertEqual(decoded.someInt, 120) + XCTAssertEqual(decoded.someString, "beep") + + let dict = try YAMLDecoder().decode([String: String].self, from: source) + XCTAssertEqual(dict["someInt"], "120") + XCTAssertEqual(dict["someString"], "beep") + XCTAssertEqual(dict.keys.count, 2) } /// A type used to contain values used during testing