Skip to content

Commit b18ba06

Browse files
committed
Parser: ensure error on tokens after doc end
1 parent 0c4db5c commit b18ba06

File tree

7 files changed

+183
-5
lines changed

7 files changed

+183
-5
lines changed

changelog/current.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
{map: }
1111
: bad
1212
```
13-
- [PR#586](https://github.com/biojppm/rapidyaml/pull/586): colon on newline generally ([play](https://play.yaml.com/?show=xd#c2NhbGFyCjogYmFkCi0tLQpbc2VxXQo6IGJhZAotLS0KW21hcF0KOiBiYWQK)):
13+
- [PR#586](https://github.com/biojppm/rapidyaml/pull/586): tokens after explicit document endcolon on newline:
1414
```yaml
1515
bad cases:
1616
scalar
@@ -20,3 +20,8 @@
2020
{map: }
2121
: bad
2222
```
23+
- [PR#586](https://github.com/biojppm/rapidyaml/pull/586): tokens after explicit document end:
24+
```yaml
25+
foo: bar
26+
... bad tokens
27+
```

src/c4/yml/parse_engine.def.hpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,6 +1786,17 @@ void ParseEngine<EventHandler>::_end_doc_suddenly()
17861786
addrem_flags(RUNK|RTOP|NDOC, RMAP|RSEQ|RDOC);
17871787
}
17881788

1789+
template<class EventHandler>
1790+
void ParseEngine<EventHandler>::_check_doc_end_tokens() const
1791+
{
1792+
csubstr rem = m_evt_handler->m_curr->line_contents.rem;
1793+
_RYML_ASSERT_PARSE_(m_evt_handler->m_stack.m_callbacks, !rem.begins_with_any(". \t"), m_evt_handler->m_curr->pos);
1794+
if(C4_UNLIKELY(rem.len && !rem.begins_with('#')))
1795+
{
1796+
_c4err("parse error");
1797+
}
1798+
}
1799+
17891800
template<class EventHandler>
17901801
void ParseEngine<EventHandler>::_start_doc_suddenly()
17911802
{
@@ -5964,6 +5975,23 @@ void ParseEngine<EventHandler>::_handle_seq_block()
59645975
_maybe_skip_whitespace_tokens();
59655976
goto seqblck_finish;
59665977
}
5978+
else if(first == '.')
5979+
{
5980+
_c4dbgp("seqblck[RVAL]: maybe end doc?");
5981+
csubstr rs = m_evt_handler->m_curr->line_contents.rem.sub(1);
5982+
if(rs == ".." || rs.begins_with(".. "))
5983+
{
5984+
_c4dbgp("seqblck[RVAL]: end+start doc");
5985+
_end_doc_suddenly();
5986+
_line_progressed(3);
5987+
_maybe_skip_whitespace_tokens();
5988+
_check_doc_end_tokens();
5989+
}
5990+
else
5991+
{
5992+
_c4err("parse error");
5993+
}
5994+
}
59675995
else
59685996
{
59695997
_c4err("parse error");
@@ -6083,10 +6111,11 @@ void ParseEngine<EventHandler>::_handle_seq_block()
60836111
csubstr rs = rem.sub(1);
60846112
if(rs == ".." || rs.begins_with(".. "))
60856113
{
6086-
_c4dbgp("seqblck[RNXT]: end+start doc");
6114+
_c4dbgp("seqblck[RNXT]: end doc");
60876115
_end_doc_suddenly();
60886116
_line_progressed(3);
60896117
_maybe_skip_whitespace_tokens();
6118+
_check_doc_end_tokens();
60906119
goto seqblck_finish;
60916120
}
60926121
else
@@ -6352,6 +6381,7 @@ void ParseEngine<EventHandler>::_handle_map_block()
63526381
_end_doc_suddenly();
63536382
_line_progressed(3);
63546383
_maybe_skip_whitespace_tokens();
6384+
_check_doc_end_tokens();
63556385
goto mapblck_finish;
63566386
}
63576387
else
@@ -6795,6 +6825,7 @@ void ParseEngine<EventHandler>::_handle_map_block()
67956825
_end_doc_suddenly();
67966826
_line_progressed(3);
67976827
_maybe_skip_whitespace_tokens();
6828+
_check_doc_end_tokens();
67986829
goto mapblck_finish;
67996830
}
68006831
else
@@ -7233,6 +7264,8 @@ bool ParseEngine<EventHandler>::_handle_map_block_qmrk()
72337264
_c4dbgp("mapblck[QMRK]: end+start doc");
72347265
_end_doc_suddenly();
72357266
_line_progressed(3);
7267+
_maybe_skip_whitespace_tokens();
7268+
_check_doc_end_tokens();
72367269
return false; // finish mapblck
72377270
}
72387271
else
@@ -7314,6 +7347,8 @@ bool ParseEngine<EventHandler>::_handle_map_block_rkcl()
73147347
_c4dbgp("mapblck[RKCL]: end+start doc");
73157348
_end_doc_suddenly();
73167349
_line_progressed(3);
7350+
_maybe_skip_whitespace_tokens();
7351+
_check_doc_end_tokens();
73177352
return false; // finish mapblck
73187353
}
73197354
else
@@ -7514,6 +7549,7 @@ void ParseEngine<EventHandler>::_handle_unk()
75147549
addrem_flags(NDOC|RUNK, RDOC);
75157550
_line_progressed(3u);
75167551
_maybe_skip_whitespace_tokens();
7552+
_check_doc_end_tokens();
75177553
return;
75187554
}
75197555
}

src/c4/yml/parse_engine.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ class ParseEngine
516516
void _begin2_doc_expl();
517517
void _end2_doc();
518518
void _end2_doc_expl();
519+
void _check_doc_end_tokens() const;
519520

520521
void _maybe_begin_doc();
521522
void _maybe_end_doc();

test/test_engine_1_doc.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,131 @@ ENGINE_TEST(DocEmptyTerm4_2,
174174
}
175175

176176

177+
ENGINE_TEST(DocEmptyTermErr,
178+
"...\n...\n"
179+
,
180+
""
181+
,
182+
"+STR\n"
183+
"-STR\n")
184+
{
185+
___(ps.begin_stream());
186+
___(ps.end_stream());
187+
}
188+
189+
190+
//-----------------------------------------------------------------------------
191+
192+
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err0,
193+
Location(2, 5),
194+
"foo: bar\n"
195+
"... bad\n"
196+
)
197+
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err1,
198+
Location(2, 5),
199+
"foo: bar\n"
200+
"... [bad]\n"
201+
)
202+
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err2,
203+
Location(2, 5),
204+
"foo: bar\n"
205+
"... {bad: yes}\n"
206+
)
207+
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err3,
208+
Location(2, 5),
209+
"foo:\n"
210+
"... bad\n"
211+
)
212+
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err4,
213+
Location(2, 5),
214+
"foo:\n"
215+
"... bad\n"
216+
)
217+
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err5,
218+
Location(2, 5),
219+
"?\n"
220+
"... bad\n"
221+
)
222+
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err6,
223+
Location(2, 5),
224+
"? foo\n"
225+
"... bad\n"
226+
)
227+
ENGINE_TEST(DocTerm_MapBlck_ok,
228+
"foo: bar\n"
229+
"... #bad\n"
230+
,
231+
"foo: bar\n"
232+
,
233+
"+STR\n"
234+
"+DOC\n"
235+
"+MAP\n"
236+
"=VAL :foo\n"
237+
"=VAL :bar\n"
238+
"-MAP\n"
239+
"-DOC ...\n"
240+
"-STR\n")
241+
{
242+
___(ps.begin_stream());
243+
___(ps.begin_doc());
244+
___(ps.begin_map_val_block());
245+
___(ps.set_key_scalar_plain("foo"));
246+
___(ps.set_val_scalar_plain("bar"));
247+
___(ps.end_map_block());
248+
___(ps.end_doc_expl());
249+
___(ps.end_stream());
250+
}
251+
252+
ENGINE_TEST_ERRLOC(DocTerm_SeqBlck_err0,
253+
Location(2, 5),
254+
"- foo\n"
255+
"... bad\n"
256+
)
257+
ENGINE_TEST_ERRLOC(DocTerm_SeqBlck_err1,
258+
Location(2, 5),
259+
"-\n"
260+
"... bad\n"
261+
)
262+
263+
ENGINE_TEST_ERRLOC(DocTerm_MapFlow_err0,
264+
Location(2, 5),
265+
"{key: val}\n"
266+
"... bad\n"
267+
)
268+
269+
ENGINE_TEST_ERRLOC(DocTerm_SeqFlow_err0,
270+
Location(2, 5),
271+
"{key: val}\n"
272+
"... bad\n"
273+
)
274+
275+
ENGINE_TEST_ERRLOC(DocTerm_ScalarPlain_err0,
276+
Location(2, 5),
277+
"scalar\n"
278+
"... bad\n"
279+
)
280+
ENGINE_TEST_ERRLOC(DocTerm_ScalarSquo_err0,
281+
Location(2, 5),
282+
"'scalar'\n"
283+
"... bad\n"
284+
)
285+
ENGINE_TEST_ERRLOC(DocTerm_ScalarDquo_err0,
286+
Location(2, 5),
287+
"\"scalar\"\n"
288+
"... bad\n"
289+
)
290+
ENGINE_TEST_ERRLOC(DocTerm_ScalarLit_err0,
291+
Location(3, 5),
292+
"|\n scalar\n"
293+
"... bad\n"
294+
)
295+
ENGINE_TEST_ERRLOC(DocTerm_FoldedLit_err0,
296+
Location(3, 5),
297+
">\n scalar\n"
298+
"... bad\n"
299+
)
300+
301+
177302
//-----------------------------------------------------------------------------
178303

179304
ENGINE_TEST(DocEmptyExplMult,

test/test_lib/test_case.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,10 @@ void ExpectError::check_error_parse(Tree *tree, fntestref fn, Location const& ex
458458
"---------------\n");
459459
}, )
460460
EXPECT_NE(context.m_error, ExpectedErrorType::err_none);
461-
EXPECT_EQ(context.m_error, ExpectedErrorType::err_parse);
461+
if(context.m_error != ExpectedErrorType::err_none)
462+
{
463+
EXPECT_EQ(context.m_error, ExpectedErrorType::err_parse);
464+
}
462465
}
463466

464467
void ExpectError::check_error_visit(Tree *tree, fntestref fn, id_type id)
@@ -498,7 +501,10 @@ void ExpectError::check_error_visit(Tree *tree, fntestref fn, id_type id)
498501
std::cout << "---------------\n";
499502
}, )
500503
EXPECT_NE(context.m_error, ExpectedErrorType::err_none);
501-
EXPECT_EQ(context.m_error, ExpectedErrorType::err_visit);
504+
if(context.m_error != ExpectedErrorType::err_none)
505+
{
506+
EXPECT_EQ(context.m_error, ExpectedErrorType::err_visit);
507+
}
502508
}
503509

504510
void ExpectError::check_assert(ExpectedErrorType errtype, Tree *tree, fntestref fn, Location const& loc)

test/testsuite.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,7 @@ struct TestSequenceData
770770
//SKIP_IF(has_container_keys); // DO IT!
771771
if(m_expected_error_to_tree_checked)
772772
return;
773+
SCOPED_TRACE("check_expected_error");
773774
ExpectError::check_error_parse(&levels[0].tree_parsed_from_src, [this]{
774775
levels[0].parse_yaml_to_tree();
775776
});
@@ -781,6 +782,7 @@ struct TestSequenceData
781782
//SKIP_IF(has_container_keys); // DO IT!
782783
if(m_expected_error_to_events_checked)
783784
return;
785+
SCOPED_TRACE("check_expected_error_events");
784786
ExpectError::check_error_parse([this]{
785787
levels[0].parse_yaml_to_events();
786788
});
@@ -792,6 +794,7 @@ struct TestSequenceData
792794
//SKIP_IF(has_container_keys); // DO IT!
793795
if(m_expected_error_to_events_ints_checked)
794796
return;
797+
SCOPED_TRACE("check_expected_error_events");
795798
ExpectError::check_error_parse([this]{
796799
levels[0].parse_yaml_to_events_ints();
797800
});
@@ -924,18 +927,21 @@ bool g_do_subcases = true;
924927
TEST(which##_errors, check_expected_error_src_to_tree) \
925928
{ \
926929
SKIP_IF(!g_suite_case->test_case_expects_error); \
930+
SCOPED_TRACE("check_expected_error_src_to_tree"); \
927931
g_suite_case->which.check_expected_error(); \
928932
} \
929933
\
930934
TEST(which##_errors, check_expected_error_src_to_events) \
931935
{ \
932936
SKIP_IF(!g_suite_case->test_case_expects_error); \
937+
SCOPED_TRACE("check_expected_error_src_to_events"); \
933938
g_suite_case->which.check_expected_error_events(); \
934939
} \
935940
\
936941
TEST(which##_errors, check_expected_error_src_to_events_ints) \
937942
{ \
938943
SKIP_IF(!g_suite_case->test_case_expects_error); \
944+
SCOPED_TRACE("check_expected_error_src_to_events_ints"); \
939945
g_suite_case->which.check_expected_error_events_ints(); \
940946
} \
941947
\

test/testsuite/testsuite_parts.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ constexpr const AllowedFailure allowed_failures[] = {
2929
// These tests are temporarily skipped, and cover issues that must be fixed.
3030

3131
// These invalid YAML cases do not materialize parse errors
32-
_("3HFZ-error" , "should not accept scalar after ..."),
3332
_("4EJS-error" , "should not accept tabs as indendation in a mapping"),
3433
_("5TRB-error" , "should not accept document-end marker in double quoted string"),
3534
_("5U3A-error" , "should not accept opening a sequence on same line as map key"),

0 commit comments

Comments
 (0)