From 58e264aab7ab0484bdd46948af37efa53f9f3c31 Mon Sep 17 00:00:00 2001 From: tdakkota Date: Sun, 23 Apr 2023 08:54:10 +0300 Subject: [PATCH] fix: require a space character between flow ending and comment --- decode_test.go | 9 +++++++++ scannerc.go | 21 ++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/decode_test.go b/decode_test.go index 5b316e6..49d970c 100644 --- a/decode_test.go +++ b/decode_test.go @@ -1485,6 +1485,15 @@ var unmarshalErrorTests = []struct { // Invalid tag UTF-8. {"a: !%C0%80 bar", "yaml: offset 3: tag contains invalid UTF-8"}, + // For some mysterious reason, YAML require a space after mapping flow end and before comment. + // + // See https://yaml.org/spec/1.2.2/#rule-s-b-comment + // + // The `s-separate-in-line` rule. + {"{{}#\n}0", "yaml: offset 3: missing space before comment"}, + {"{}#", "yaml: offset 2: missing space before comment"}, + {"[]#", "yaml: offset 2: missing space before comment"}, + // From https://github.com/go-yaml/yaml/pull/921. {"a:\n- b: *,", `yaml: line 2:5: did not find expected alphabetic or numeric character`}, {"a:\n- b: *a{", `yaml: line 2:5: did not find expected alphabetic or numeric character`}, diff --git a/scannerc.go b/scannerc.go index f0c18b4..ff3a175 100644 --- a/scannerc.go +++ b/scannerc.go @@ -748,6 +748,7 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { // Associate any following comments with the prior token. comment_mark = parser.tokens[len(parser.tokens)-1].start_mark } + var need_before_comment_space bool defer func() { if !ok { return @@ -757,7 +758,7 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { // a head comment for whatever follows. return } - if !yaml_parser_scan_line_comment(parser, comment_mark) { + if !yaml_parser_scan_line_comment(parser, comment_mark, need_before_comment_space) { ok = false return } @@ -775,12 +776,14 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { // Is it the flow sequence end indicator? if parser.buffer[parser.buffer_pos] == ']' { + need_before_comment_space = true return yaml_parser_fetch_flow_collection_end(parser, yaml_FLOW_SEQUENCE_END_TOKEN) } // Is it the flow mapping end indicator? if parser.buffer[parser.buffer_pos] == '}' { + need_before_comment_space = true return yaml_parser_fetch_flow_collection_end(parser, yaml_FLOW_MAPPING_END_TOKEN) } @@ -2289,7 +2292,7 @@ func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, l } } if parser.buffer[parser.buffer_pos] == '#' { - if !yaml_parser_scan_line_comment(parser, start_mark) { + if !yaml_parser_scan_line_comment(parser, start_mark, false) { return false } for !is_breakz(parser.buffer, parser.buffer_pos) { @@ -2886,22 +2889,30 @@ func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) b return true } -func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool { +func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t, need_space_before_comment bool) bool { if parser.newlines > 0 { return true } - var start_mark yaml_mark_t - var text []byte + var ( + text []byte + start_mark yaml_mark_t + has_space_before bool + ) for peek := 0; peek < 512; peek++ { if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { break } if is_blank(parser.buffer, parser.buffer_pos+peek) { + has_space_before = true continue } if parser.buffer[parser.buffer_pos+peek] == '#' { + if need_space_before_comment && !has_space_before { + yaml_parser_set_scanner_error(parser, "while scanning a comment", token_mark, "missing space before comment") + return false + } seen := parser.mark.index + peek for { if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {