From 24bb2ea4dda710d3e5b49d81d0ce75e5e5c928c3 Mon Sep 17 00:00:00 2001 From: Mihaela Mihaljevic Date: Wed, 24 Jun 2026 21:53:48 +0200 Subject: [PATCH] fix(parsing): also reject a plain multi-line key in a flow sequence A flow-sequence single-pair implicit key must be single-line, so its ':' must sit on the key's line. The quoted form ('[ "key"\n :value ]') was already rejected via a crossed line break, but a plain key folds its line break, hiding it. Compare the simple key's mark line with the ':' line instead, which catches both forms and still exempts flow mappings. Surpasses libyaml on DK4H (and keeps ZXT5); whole-suite conformance 398/402, canonical events 308/308. --- CHANGELOG.md | 11 ++++++----- Sources/Parsing/LibYAML.Scanner.Fetch.swift | 5 +++-- Tests/Fixtures/yaml-test-suite-manifest.yaml | 6 +++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5146672..23f3694 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,11 +23,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Reject a multi-line implicit key in a flow sequence. A flow-sequence single-pair - implicit key is single-line (`c-s-implicit-json-key`), so its `:` may not cross a - line break: `[ "key"\n :value ]` is malformed. A flow MAPPING adjacent value may - still span lines (`{ "foo"\n :bar }` stays valid), so the rejection is scoped to - flow levels that are sequences, tracked alongside the flow-level stack. Surpasses - libyaml on ZXT5. + implicit key is single-line (`c-s-implicit-json-key`), so its `:` must sit on the + key's line: both `[ "key"\n :value ]` and `[ key\n : value ]` are malformed. A + flow MAPPING adjacent value may still span lines (`{ "foo"\n :bar }` stays + valid), so the rejection is scoped to flow levels that are sequences, tracked + alongside the flow-level stack. The key/`:` line comparison catches the plain-key + form too, which folds its line break. Surpasses libyaml on ZXT5 and DK4H. - Reject a block sequence that opens on the same line as an earlier node. A `-` entry mid-line after an inline mapping value (`key: - a`) or a node property (`&anchor - x`) is invalid, while a `-` after another `-` stays a valid compact diff --git a/Sources/Parsing/LibYAML.Scanner.Fetch.swift b/Sources/Parsing/LibYAML.Scanner.Fetch.swift index becfe59..6db7da3 100644 --- a/Sources/Parsing/LibYAML.Scanner.Fetch.swift +++ b/Sources/Parsing/LibYAML.Scanner.Fetch.swift @@ -314,8 +314,9 @@ extension PureYAML.Parsing.LibYAML.Scanner { // (it went stale across the line break), so its value may open a sequence. lastValueWasInline = simpleKeys[top].possible // A flow-sequence single-pair implicit key must be single-line, so its `:` - // may not cross a line break; a flow-mapping adjacent value may. - if simpleKeys[top].possible, crossedLineBreak, flowIsSequence.last == true { + // must sit on the key's line (`[ "k"\n :v ]` and `[ k\n : v ]` are both + // invalid); a flow-mapping adjacent value may span lines (`{ "k"\n :v }`). + if simpleKeys[top].possible, flowIsSequence.last == true, simpleKeys[top].mark.line != mark.line { throw ScannerError( context: "while scanning a simple key", problem: "could not find expected ':'", diff --git a/Tests/Fixtures/yaml-test-suite-manifest.yaml b/Tests/Fixtures/yaml-test-suite-manifest.yaml index 73a15f6..9aaba07 100644 --- a/Tests/Fixtures/yaml-test-suite-manifest.yaml +++ b/Tests/Fixtures/yaml-test-suite-manifest.yaml @@ -10,8 +10,8 @@ source: # oracle: json if in.json present, else none # status: passing (PureYAML conformant today) | gap (not yet conformant) total: 402 -passing: 397 -gap: 5 +passing: 398 +gap: 4 cases: - id: "229Q" name: "Spec Example 2.4. Sequence of Mappings" @@ -1490,7 +1490,7 @@ cases: localPath: yaml-test-suite/DK4H/in.yaml expected: reject oracle: none - status: gap + status: passing byteCount: 22 lineCount: 3 - id: "DK95/00"