diff --git a/llvm/lib/Support/YAMLParser.cpp b/llvm/lib/Support/YAMLParser.cpp --- a/llvm/lib/Support/YAMLParser.cpp +++ b/llvm/lib/Support/YAMLParser.cpp @@ -789,6 +789,7 @@ if (TokenQueue.empty() || NeedMore) { if (!fetchMoreTokens()) { TokenQueue.clear(); + SimpleKeys.clear(); TokenQueue.push_back(Token()); return TokenQueue.front(); } @@ -932,12 +933,16 @@ } bool Scanner::consume(uint32_t Expected) { - if (Expected >= 0x80) - report_fatal_error("Not dealing with this yet"); + if (Expected >= 0x80) { + setError("Cannot consume non-ascii characters"); + return false; + } if (Current == End) return false; - if (uint8_t(*Current) >= 0x80) - report_fatal_error("Not dealing with this yet"); + if (uint8_t(*Current) >= 0x80) { + setError("Cannot consume non-ascii characters"); + return false; + } if (uint8_t(*Current) == Expected) { ++Current; ++Column; @@ -1227,7 +1232,10 @@ if (i == SK.Tok) break; } - assert(i != e && "SimpleKey not in token queue!"); + if (i == e) { + Failed = true; + return false; + } i = TokenQueue.insert(i, T); // We may also need to add a Block-Mapping-Start token. @@ -1772,10 +1780,11 @@ bool Stream::failed() { return scanner->failed(); } void Stream::printError(Node *N, const Twine &Msg) { - scanner->printError( N->getSourceRange().Start + SMRange Range = N ? N->getSourceRange() : SMRange(); + scanner->printError( Range.Start , SourceMgr::DK_Error , Msg - , N->getSourceRange()); + , Range); } document_iterator Stream::begin() { @@ -1934,15 +1943,18 @@ UnquotedValue = UnquotedValue.substr(1); break; default: - if (UnquotedValue.size() == 1) - // TODO: Report error. - break; + if (UnquotedValue.size() == 1) { + Token T; + T.Range = StringRef(UnquotedValue.begin(), 1); + setError("Unrecognized escape code", T); + return ""; + } UnquotedValue = UnquotedValue.substr(1); switch (UnquotedValue[0]) { default: { Token T; T.Range = StringRef(UnquotedValue.begin(), 1); - setError("Unrecognized escape code!", T); + setError("Unrecognized escape code", T); return ""; } case '\r': @@ -2078,7 +2090,14 @@ Node *KeyValueNode::getValue() { if (Value) return Value; - getKey()->skip(); + + if (Node* Key = getKey()) + Key->skip(); + else { + setError("Null key in Key Value.", peekNext()); + return Value = new (getAllocator()) NullNode(Doc); + } + if (failed()) return Value = new (getAllocator()) NullNode(Doc); @@ -2394,6 +2413,15 @@ // TODO: Properly handle tags. "[!!str ]" should resolve to !!str "", not // !!null null. return new (NodeAllocator) NullNode(stream.CurrentDoc); + case Token::TK_FlowMappingEnd: + case Token::TK_FlowSequenceEnd: + case Token::TK_FlowEntry: { + if (Root && (isa(Root) || isa(Root))) + return new (NodeAllocator) NullNode(stream.CurrentDoc); + + setError("Unexpected token", T); + return nullptr; + } case Token::TK_Error: return nullptr; } diff --git a/llvm/lib/Support/YAMLTraits.cpp b/llvm/lib/Support/YAMLTraits.cpp --- a/llvm/lib/Support/YAMLTraits.cpp +++ b/llvm/lib/Support/YAMLTraits.cpp @@ -87,7 +87,6 @@ if (DocIterator != Strm->end()) { Node *N = DocIterator->getRoot(); if (!N) { - assert(Strm->failed() && "Root is NULL iff parsing failed"); EC = make_error_code(errc::invalid_argument); return false; } @@ -371,17 +370,17 @@ std::unique_ptr Input::createHNodes(Node *N) { SmallString<128> StringStorage; - if (ScalarNode *SN = dyn_cast(N)) { + if (ScalarNode *SN = dyn_cast_or_null(N)) { StringRef KeyStr = SN->getValue(StringStorage); if (!StringStorage.empty()) { // Copy string to permanent storage KeyStr = StringStorage.str().copy(StringAllocator); } return std::make_unique(N, KeyStr); - } else if (BlockScalarNode *BSN = dyn_cast(N)) { + } else if (BlockScalarNode *BSN = dyn_cast_or_null(N)) { StringRef ValueCopy = BSN->getValue().copy(StringAllocator); return std::make_unique(N, ValueCopy); - } else if (SequenceNode *SQ = dyn_cast(N)) { + } else if (SequenceNode *SQ = dyn_cast_or_null(N)) { auto SQHNode = std::make_unique(N); for (Node &SN : *SQ) { auto Entry = createHNodes(&SN); @@ -390,11 +389,11 @@ SQHNode->Entries.push_back(std::move(Entry)); } return std::move(SQHNode); - } else if (MappingNode *Map = dyn_cast(N)) { + } else if (MappingNode *Map = dyn_cast_or_null(N)) { auto mapHNode = std::make_unique(N); for (KeyValueNode &KVN : *Map) { Node *KeyNode = KVN.getKey(); - ScalarNode *Key = dyn_cast(KeyNode); + ScalarNode *Key = dyn_cast_or_null(KeyNode); Node *Value = KVN.getValue(); if (!Key || !Value) { if (!Key) diff --git a/llvm/unittests/Support/YAMLIOTest.cpp b/llvm/unittests/Support/YAMLIOTest.cpp --- a/llvm/unittests/Support/YAMLIOTest.cpp +++ b/llvm/unittests/Support/YAMLIOTest.cpp @@ -3005,3 +3005,55 @@ EXPECT_EQ(bar->DoubleValue, 2.0); } } + +TEST(YAMLIO, TestAnchorMapError) { + Input yin("& & &: "); + yin.setCurrentDocument(); + EXPECT_TRUE(yin.error()); +} + +TEST(YAMLIO, TestFlowSequenceTokenErrors) { + Input yin(","); + EXPECT_FALSE(yin.setCurrentDocument()); + EXPECT_TRUE(yin.error()); + + Input yin2("]"); + EXPECT_FALSE(yin2.setCurrentDocument()); + EXPECT_TRUE(yin2.error()); + + Input yin3("}"); + EXPECT_FALSE(yin3.setCurrentDocument()); + EXPECT_TRUE(yin3.error()); +} + +TEST(YAMLIO, TestDirectiveMappingNoValue) { + Input yin("%YAML\n{5:"); + EXPECT_FALSE(yin.setCurrentDocument()); + EXPECT_TRUE(yin.error()); + + Input yin2("%TAG\n'\x98!< :\n"); + yin2.setCurrentDocument(); + EXPECT_TRUE(yin2.error()); +} + +TEST(YAMLIO, TestUnescapeInfiniteLoop) { + Input yin("\"\\u\\^#\\\\\""); + yin.setCurrentDocument(); + EXPECT_TRUE(yin.error()); +} + +TEST(YAMLIO, TestScannerUnexpectedCharacter) { + Input yin("!<$\x9F."); + EXPECT_FALSE(yin.setCurrentDocument()); + EXPECT_TRUE(yin.error()); +} + +TEST(YAMLIO, TestUnknownDirective) { + Input yin("%"); + EXPECT_FALSE(yin.setCurrentDocument()); + EXPECT_TRUE(yin.error()); + + Input yin2("%)"); + EXPECT_FALSE(yin2.setCurrentDocument()); + EXPECT_TRUE(yin2.error()); +}