diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index 607055341..83a65d3b4 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -92,6 +92,8 @@ const char* const BAD_FILE = "bad file"; const char* const UNEXPECTED_TOKEN_AFTER_DOC = "unexpected token after end of document"; const char* const NON_UNIQUE_MAP_KEY = "map keys must be unique"; +const char* const INDENT_STACK_UNDERFLOW = "indentation stack underflow (please report this bug to yaml-cpp)"; + template inline const std::string KEY_NOT_FOUND_WITH_KEY( const T&, typename disable_if>::type* = 0) { diff --git a/src/scanner.cpp b/src/scanner.cpp index 211e19697..a0abd3b61 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -177,7 +177,15 @@ void Scanner::ScanNextToken() { // scalar if (!m_simpleKeys.empty() && m_simpleKeys.top().pKey->status == Token::UNVERIFIED) { + // if the top of the indents does not match the unverified simple key, + // just invalidate the simple key and do not pop indent to avoid crash. + // eg: an unverified key crossing lines, like issue #1475. + if (m_simpleKeys.top().pIndent && !m_indents.empty() && + m_indents.top() == m_simpleKeys.top().pIndent) { PopIndent(); + } else { + InvalidateSimpleKey(); + } } return ScanBlockScalar(); } @@ -393,6 +401,9 @@ void Scanner::PopAllIndents() { } void Scanner::PopIndent() { + if (m_indents.empty()) { + ThrowParserException(ErrorMsg::INDENT_STACK_UNDERFLOW); + } const IndentMarker& indent = *m_indents.top(); m_indents.pop(); diff --git a/test/integration/handler_test.cpp b/test/integration/handler_test.cpp index fe389dbf9..13005df3e 100644 --- a/test/integration/handler_test.cpp +++ b/test/integration/handler_test.cpp @@ -73,6 +73,13 @@ TEST_F(HandlerTest, CommentOnNewlineOfMapValueWithManySpace) { Parse("key: value\n # comment"); } +// example from issue #1475: a stale simple key (from a plain scalar spanning +// a line break) must not pop an unrelated indent when parsing a block scalar +TEST_F(HandlerTest, LiteralScalarWithMultiLineUnverifiedPotentialSimpleKey) { + EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse("!\n: |\nb\n>\n|\n !\n>"), + ErrorMsg::END_OF_MAP); +} + // examples from issue #1163 TEST_F(HandlerTest, LiteralScalarWithTagAndLargeIndentation) { EXPECT_CALL(handler, OnDocumentStart(_));