Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions changelog/current.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
- Ensure parse errors for invalid YAML cases:
- [PR#585](https://github.com/biojppm/rapidyaml/pull/585): colon on newline at top level ([play](https://play.yaml.com/?show=xd#c2NhbGFyCjogYmFkCi0tLQpbc2VxXQo6IGJhZAotLS0KW21hcF0KOiBiYWQK)):
```yaml
scalar
: bad
---
[seq]
: bad
---
{map: }
: bad
```
- [PR#586](https://github.com/biojppm/rapidyaml/pull/586): tokens after explicit document endcolon on newline:
```yaml
bad cases:
scalar
: bad
[seq]
: bad
{map: }
: bad
```
- [PR#586](https://github.com/biojppm/rapidyaml/pull/586): tokens after explicit document end:
```yaml
foo: bar
... bad tokens
```
2 changes: 1 addition & 1 deletion src/c4/yml/event_handler_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ struct EventHandlerTree : public EventHandlerStack<EventHandlerTree, EventHandle
{
_RYML_ASSERT_BASIC_(m_stack.m_callbacks, m_tree != nullptr);
if(m_num_directives && !m_tree->is_stream(m_tree->root_id()))
_RYML_ERR_BASIC_(m_stack.m_callbacks, "directives cannot be used without a document");
_RYML_ERR_PARSE_(m_stack.m_callbacks, m_curr->pos, "directives cannot be used without a document");
this->_stack_finish_parse();
/* This pointer is temporary. Remember that:
*
Expand Down
1,376 changes: 716 additions & 660 deletions src/c4/yml/parse_engine.def.hpp

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions src/c4/yml/parse_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ class ParseEngine
private:

void _handle_map_block();
bool _handle_map_block_qmrk();
bool _handle_map_block_rkcl();
void _handle_seq_block();
void _handle_map_flow();
void _handle_seq_flow();
Expand All @@ -507,12 +509,14 @@ class ParseEngine
void _end_seq_blck();
void _end2_map();
void _end2_seq();
void _end_flow_container(size_t orig_indent);
void _flow_container_was_a_key(size_t orig_indent);

void _begin2_doc();
void _begin2_doc_expl();
void _end2_doc();
void _end2_doc_expl();
void _check_doc_end_tokens() const;

void _maybe_begin_doc();
void _maybe_end_doc();
Expand Down Expand Up @@ -605,10 +609,10 @@ class ParseEngine

#ifndef RYML_DBG
C4_ALWAYS_INLINE static void add_flags(ParserFlag_t on, ParserState *C4_RESTRICT s) noexcept { s->flags |= on; }
C4_ALWAYS_INLINE static void addrem_flags(ParserFlag_t on, ParserFlag_t off, ParserState *C4_RESTRICT s) noexcept { s->flags &= ~off; s->flags |= on; }
C4_ALWAYS_INLINE static void addrem_flags(ParserFlag_t on, ParserFlag_t off, ParserState *C4_RESTRICT s) noexcept { _RYML_ASSERT_BASIC((on & off) == 0); s->flags &= ~off; s->flags |= on; }
C4_ALWAYS_INLINE static void rem_flags(ParserFlag_t off, ParserState *C4_RESTRICT s) noexcept { s->flags &= ~off; }
C4_ALWAYS_INLINE void add_flags(ParserFlag_t on) noexcept { m_evt_handler->m_curr->flags |= on; }
C4_ALWAYS_INLINE void addrem_flags(ParserFlag_t on, ParserFlag_t off) noexcept { m_evt_handler->m_curr->flags &= ~off; m_evt_handler->m_curr->flags |= on; }
C4_ALWAYS_INLINE void addrem_flags(ParserFlag_t on, ParserFlag_t off) noexcept { _RYML_ASSERT_BASIC((on & off) == 0); m_evt_handler->m_curr->flags &= ~off; m_evt_handler->m_curr->flags |= on; }
C4_ALWAYS_INLINE void rem_flags(ParserFlag_t off) noexcept { m_evt_handler->m_curr->flags &= ~off; }
#else
static void add_flags(ParserFlag_t on, ParserState *C4_RESTRICT s);
Expand Down Expand Up @@ -694,7 +698,6 @@ class ParseEngine
Annotation m_pending_anchors;
Annotation m_pending_tags;

bool m_was_inside_qmrk;
bool m_doc_empty = true;
size_t m_prev_colon = npos;

Expand Down
5 changes: 3 additions & 2 deletions src_extra/c4/yml/extra/event_handler_ints.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,9 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack<EventHandlerInts, Ev
return m_arena_pos;
}

/** Predicate to test if the event buffer successfully accomodated
* all the parse events.
/** Predicate to test if the event and arena buffers successfully
* accomodated all the parse events.
*
* @warning this is valid only until the next parse */
bool fits_buffers() const
{
Expand Down
6 changes: 4 additions & 2 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ endfunction()

ryml_add_test(engine_1_doc)
ryml_add_test(engine_2_seq)
ryml_add_test(engine_3_map)
ryml_add_test(engine_3_map_1)
ryml_add_test(engine_3_map_2)
ryml_add_test(engine_4_anchor)
ryml_add_test(engine_5_tag)
ryml_add_test(engine_6_qmrk_1)
Expand Down Expand Up @@ -163,7 +164,8 @@ endif()
if(MSVC)
target_compile_options(ryml-test-engine_1_doc PRIVATE /bigobj)
target_compile_options(ryml-test-engine_2_seq PRIVATE /bigobj)
target_compile_options(ryml-test-engine_3_map PRIVATE /bigobj)
target_compile_options(ryml-test-engine_3_map_1 PRIVATE /bigobj)
target_compile_options(ryml-test-engine_3_map_2 PRIVATE /bigobj)
target_compile_options(ryml-test-engine_4_anchor PRIVATE /bigobj)
target_compile_options(ryml-test-engine_5_tag PRIVATE /bigobj)
target_compile_options(ryml-test-engine_6_qmrk_1 PRIVATE /bigobj)
Expand Down
4 changes: 2 additions & 2 deletions test/test_anchor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -771,13 +771,13 @@ TEST(simple_anchor, resolve_nested)
}
{
Tree t = parse_in_arena(yaml);
ExpectError::check_error_basic(&t, [&]{
ExpectError::check_error_visit(&t, [&]{
t.resolve(true);
});
}
{
Tree t = parse_in_arena(yaml);
ExpectError::check_error_basic(&t, [&]{
ExpectError::check_error_visit(&t, [&]{
t.resolve(false);
});
}
Expand Down
2 changes: 1 addition & 1 deletion test/test_bom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void test_bom2(bom2spec const& spec, CreateFn &&createfn, TestFn &&testfn, bom2_
else
{
pfn_error_basic orig = get_callbacks().m_error_basic;
ExpectError::check_error_basic([&]{
ExpectError::check_error_parse([&]{
Parser::handler_type handler;
Parser parser(&handler);
Tree tree;
Expand Down
48 changes: 24 additions & 24 deletions test/test_emit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,14 +356,14 @@ void test_emits(Tree const& t, id_type id, std::string const& expected, std::str
{
EmitOptions optsd = opts;
optsd = optsd.max_depth(0);
ExpectError::check_error_basic(&t, [&]{ return emit2buf([&](substr buf){ return emit_yaml(t, id, optsd, buf); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2buf([&](substr buf){ return emit_json(t, id, optsd, buf); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2file([&](FILE *f){ return emit_yaml(t, id, optsd, f); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2file([&](FILE *f){ return emit_json(t, id, optsd, f); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(t, id, optsd); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(t, id, optsd); }); });
ExpectError::check_error_basic(&t, [&]{ return emitrs_yaml<std::string>(t, id, optsd); });
ExpectError::check_error_basic(&t, [&]{ return emitrs_json<std::string>(t, id, optsd); });
ExpectError::check_error_visit(&t, [&]{ return emit2buf([&](substr buf){ return emit_yaml(t, id, optsd, buf); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2buf([&](substr buf){ return emit_json(t, id, optsd, buf); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2file([&](FILE *f){ return emit_yaml(t, id, optsd, f); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2file([&](FILE *f){ return emit_json(t, id, optsd, f); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(t, id, optsd); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(t, id, optsd); }); });
ExpectError::check_error_visit(&t, [&]{ return emitrs_yaml<std::string>(t, id, optsd); });
ExpectError::check_error_visit(&t, [&]{ return emitrs_json<std::string>(t, id, optsd); });
}
}

Expand Down Expand Up @@ -414,14 +414,14 @@ void test_emits(Tree const& t, std::string const& expected, std::string const& e
{
EmitOptions optsd = opts;
optsd = optsd.max_depth(0);
ExpectError::check_error_basic(&t, [&]{ return emit2buf([&](substr buf){ return emit_yaml(t, optsd, buf); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2buf([&](substr buf){ return emit_json(t, optsd, buf); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2file([&](FILE *f){ return emit_yaml(t, optsd, f); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2file([&](FILE *f){ return emit_json(t, optsd, f); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(ConstNodeRef(&t), optsd); }); });
ExpectError::check_error_basic(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(ConstNodeRef(&t), optsd); }); });
ExpectError::check_error_basic(&t, [&]{ return emitrs_yaml<std::string>(t, optsd); });
ExpectError::check_error_basic(&t, [&]{ return emitrs_json<std::string>(t, optsd); });
ExpectError::check_error_visit(&t, [&]{ return emit2buf([&](substr buf){ return emit_yaml(t, optsd, buf); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2buf([&](substr buf){ return emit_json(t, optsd, buf); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2file([&](FILE *f){ return emit_yaml(t, optsd, f); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2file([&](FILE *f){ return emit_json(t, optsd, f); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(ConstNodeRef(&t), optsd); }); });
ExpectError::check_error_visit(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(ConstNodeRef(&t), optsd); }); });
ExpectError::check_error_visit(&t, [&]{ return emitrs_yaml<std::string>(t, optsd); });
ExpectError::check_error_visit(&t, [&]{ return emitrs_json<std::string>(t, optsd); });
}
}

Expand Down Expand Up @@ -471,14 +471,14 @@ void test_emits(ConstNodeRef n, std::string const& expected, std::string const&
{
EmitOptions optsd = opts;
optsd = optsd.max_depth(0);
ExpectError::check_error_basic(n.tree(), [&]{ return emit2buf([&](substr buf){ return emit_yaml(n, optsd, buf); }); });
ExpectError::check_error_basic(n.tree(), [&]{ return emit2buf([&](substr buf){ return emit_json(n, optsd, buf); }); });
ExpectError::check_error_basic(n.tree(), [&]{ return emit2file([&](FILE *f){ return emit_yaml(n, optsd, f); }); });
ExpectError::check_error_basic(n.tree(), [&]{ return emit2file([&](FILE *f){ return emit_json(n, optsd, f); }); });
ExpectError::check_error_basic(n.tree(), [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(n, optsd); }); });
ExpectError::check_error_basic(n.tree(), [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(n, optsd); }); });
ExpectError::check_error_basic(n.tree(), [&]{ return emitrs_yaml<std::string>(n, optsd); });
ExpectError::check_error_basic(n.tree(), [&]{ return emitrs_json<std::string>(n, optsd); });
ExpectError::check_error_visit(n.tree(), [&]{ return emit2buf([&](substr buf){ return emit_yaml(n, optsd, buf); }); });
ExpectError::check_error_visit(n.tree(), [&]{ return emit2buf([&](substr buf){ return emit_json(n, optsd, buf); }); });
ExpectError::check_error_visit(n.tree(), [&]{ return emit2file([&](FILE *f){ return emit_yaml(n, optsd, f); }); });
ExpectError::check_error_visit(n.tree(), [&]{ return emit2file([&](FILE *f){ return emit_json(n, optsd, f); }); });
ExpectError::check_error_visit(n.tree(), [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(n, optsd); }); });
ExpectError::check_error_visit(n.tree(), [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(n, optsd); }); });
ExpectError::check_error_visit(n.tree(), [&]{ return emitrs_yaml<std::string>(n, optsd); });
ExpectError::check_error_visit(n.tree(), [&]{ return emitrs_json<std::string>(n, optsd); });
}
}
}
Expand Down
125 changes: 125 additions & 0 deletions test/test_engine_1_doc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,131 @@ ENGINE_TEST(DocEmptyTerm4_2,
}


ENGINE_TEST(DocEmptyTermErr,
"...\n...\n"
,
""
,
"+STR\n"
"-STR\n")
{
___(ps.begin_stream());
___(ps.end_stream());
}


//-----------------------------------------------------------------------------

ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err0,
Location(2, 5),
"foo: bar\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err1,
Location(2, 5),
"foo: bar\n"
"... [bad]\n"
)
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err2,
Location(2, 5),
"foo: bar\n"
"... {bad: yes}\n"
)
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err3,
Location(2, 5),
"foo:\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err4,
Location(2, 5),
"foo:\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err5,
Location(2, 5),
"?\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_MapBlck_err6,
Location(2, 5),
"? foo\n"
"... bad\n"
)
ENGINE_TEST(DocTerm_MapBlck_ok,
"foo: bar\n"
"... #bad\n"
,
"foo: bar\n"
,
"+STR\n"
"+DOC\n"
"+MAP\n"
"=VAL :foo\n"
"=VAL :bar\n"
"-MAP\n"
"-DOC ...\n"
"-STR\n")
{
___(ps.begin_stream());
___(ps.begin_doc());
___(ps.begin_map_val_block());
___(ps.set_key_scalar_plain("foo"));
___(ps.set_val_scalar_plain("bar"));
___(ps.end_map_block());
___(ps.end_doc_expl());
___(ps.end_stream());
}

ENGINE_TEST_ERRLOC(DocTerm_SeqBlck_err0,
Location(2, 5),
"- foo\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_SeqBlck_err1,
Location(2, 5),
"-\n"
"... bad\n"
)

ENGINE_TEST_ERRLOC(DocTerm_MapFlow_err0,
Location(2, 5),
"{key: val}\n"
"... bad\n"
)

ENGINE_TEST_ERRLOC(DocTerm_SeqFlow_err0,
Location(2, 5),
"{key: val}\n"
"... bad\n"
)

ENGINE_TEST_ERRLOC(DocTerm_ScalarPlain_err0,
Location(2, 5),
"scalar\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_ScalarSquo_err0,
Location(2, 5),
"'scalar'\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_ScalarDquo_err0,
Location(2, 5),
"\"scalar\"\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_ScalarLit_err0,
Location(3, 5),
"|\n scalar\n"
"... bad\n"
)
ENGINE_TEST_ERRLOC(DocTerm_FoldedLit_err0,
Location(3, 5),
">\n scalar\n"
"... bad\n"
)


//-----------------------------------------------------------------------------

ENGINE_TEST(DocEmptyExplMult,
Expand Down
Loading
Loading