diff --git a/include/fkYAML/detail/input/deserializer.hpp b/include/fkYAML/detail/input/deserializer.hpp index 607fe1b0..4664ee7a 100644 --- a/include/fkYAML/detail/input/deserializer.hpp +++ b/include/fkYAML/detail/input/deserializer.hpp @@ -165,6 +165,8 @@ class basic_deserializer { /// @param lexer The lexical analyzer to be used. /// @param last_type The variable to store the last lexical token type. void deserialize_directives(lexer_type& lexer, lexical_token_t& last_type) { + bool lacks_end_of_directives_marker = false; + for (;;) { lexical_token_t type = lexer.get_next_token(); @@ -179,6 +181,7 @@ class basic_deserializer { mp_meta->version = convert_yaml_version(lexer.get_yaml_version()); mp_meta->is_version_specified = true; + lacks_end_of_directives_marker = true; break; case lexical_token_t::TAG_DIRECTIVE: { const std::string& tag_handle = lexer.get_tag_handle(); @@ -192,6 +195,7 @@ class basic_deserializer { lexer.get_last_token_begin_pos()); } mp_meta->primary_handle_prefix = lexer.get_tag_prefix(); + lacks_end_of_directives_marker = true; break; } case 2: { @@ -203,6 +207,7 @@ class basic_deserializer { lexer.get_last_token_begin_pos()); } mp_meta->secondary_handle_prefix = lexer.get_tag_prefix(); + lacks_end_of_directives_marker = true; break; } default: { @@ -214,6 +219,7 @@ class basic_deserializer { lexer.get_lines_processed(), lexer.get_last_token_begin_pos()); } + lacks_end_of_directives_marker = true; break; } } @@ -223,9 +229,15 @@ class basic_deserializer { // TODO: should output a warning log. Currently just ignore this case. break; case lexical_token_t::END_OF_DIRECTIVES: - // Ignore this directives end marker so the caller will get the beginning token of the contents. + lacks_end_of_directives_marker = false; break; default: + if (lacks_end_of_directives_marker) { + throw parse_error( + "The end of directives marker (---) is missing after directives.", + lexer.get_lines_processed(), + lexer.get_last_token_begin_pos()); + } // end the parsing of directives if the other tokens are found. last_type = type; return; diff --git a/single_include/fkYAML/node.hpp b/single_include/fkYAML/node.hpp index bec30513..d195a916 100644 --- a/single_include/fkYAML/node.hpp +++ b/single_include/fkYAML/node.hpp @@ -4394,6 +4394,8 @@ class basic_deserializer { /// @param lexer The lexical analyzer to be used. /// @param last_type The variable to store the last lexical token type. void deserialize_directives(lexer_type& lexer, lexical_token_t& last_type) { + bool lacks_end_of_directives_marker = false; + for (;;) { lexical_token_t type = lexer.get_next_token(); @@ -4408,6 +4410,7 @@ class basic_deserializer { mp_meta->version = convert_yaml_version(lexer.get_yaml_version()); mp_meta->is_version_specified = true; + lacks_end_of_directives_marker = true; break; case lexical_token_t::TAG_DIRECTIVE: { const std::string& tag_handle = lexer.get_tag_handle(); @@ -4421,6 +4424,7 @@ class basic_deserializer { lexer.get_last_token_begin_pos()); } mp_meta->primary_handle_prefix = lexer.get_tag_prefix(); + lacks_end_of_directives_marker = true; break; } case 2: { @@ -4432,6 +4436,7 @@ class basic_deserializer { lexer.get_last_token_begin_pos()); } mp_meta->secondary_handle_prefix = lexer.get_tag_prefix(); + lacks_end_of_directives_marker = true; break; } default: { @@ -4443,6 +4448,7 @@ class basic_deserializer { lexer.get_lines_processed(), lexer.get_last_token_begin_pos()); } + lacks_end_of_directives_marker = true; break; } } @@ -4452,9 +4458,15 @@ class basic_deserializer { // TODO: should output a warning log. Currently just ignore this case. break; case lexical_token_t::END_OF_DIRECTIVES: - // Ignore this directives end marker so the caller will get the beginning token of the contents. + lacks_end_of_directives_marker = false; break; default: + if (lacks_end_of_directives_marker) { + throw parse_error( + "The end of directives marker (---) is missing after directives.", + lexer.get_lines_processed(), + lexer.get_last_token_begin_pos()); + } // end the parsing of directives if the other tokens are found. last_type = type; return; diff --git a/test/unit_test/test_deserializer_class.cpp b/test/unit_test/test_deserializer_class.cpp index 260bfa8b..82f59648 100644 --- a/test/unit_test/test_deserializer_class.cpp +++ b/test/unit_test/test_deserializer_class.cpp @@ -1921,6 +1921,11 @@ TEST_CASE("Deserializer_YAMLVerDirective") { REQUIRE_THROWS_AS( deserializer.deserialize(fkyaml::detail::input_adapter("%YAML 1.1\n%YAML 1.2\n")), fkyaml::parse_error); } + + SECTION("lacks the end of directives marker after YAML directive") { + REQUIRE_THROWS_AS( + deserializer.deserialize(fkyaml::detail::input_adapter("%YAML 1.2\nfoo: bar")), fkyaml::parse_error); + } } TEST_CASE("Deserializer_TagDirective") { @@ -2010,6 +2015,12 @@ TEST_CASE("Deserializer_TagDirective") { "foo: bar"; REQUIRE_THROWS_AS(deserializer.deserialize(fkyaml::detail::input_adapter(input)), fkyaml::parse_error); } + + SECTION("lacks the end of directives marker after TAG directive") { + std::string input = "%TAG ! tag:test.com,2000:\n" + "foo: bar"; + REQUIRE_THROWS_AS(deserializer.deserialize(fkyaml::detail::input_adapter(input)), fkyaml::parse_error); + } } TEST_CASE("Deserializer_InvalidDirective") {