summaryrefslogtreecommitdiff
path: root/lib/Support
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2013-11-18 15:50:04 +0000
committerAlexander Kornienko <alexfh@google.com>2013-11-18 15:50:04 +0000
commit6919bec07f9c4ee57a0e99f263b63546b386f22b (patch)
treefbcc184fdb7bc34d620d9a550965b38e717bbab5 /lib/Support
parent64409ad8e3b360b84349042f14b57f87a5c0ca18 (diff)
downloadllvm-6919bec07f9c4ee57a0e99f263b63546b386f22b.tar.gz
llvm-6919bec07f9c4ee57a0e99f263b63546b386f22b.tar.bz2
llvm-6919bec07f9c4ee57a0e99f263b63546b386f22b.tar.xz
Recover gracefully when deserializing invalid YAML input.
Fixes http://llvm.org/PR16221, http://llvm.org/PR15927 Phabricator: http://llvm-reviews.chandlerc.com/D1236 Patch by Andrew Tulloch! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195016 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support')
-rw-r--r--lib/Support/YAMLTraits.cpp33
1 files changed, 26 insertions, 7 deletions
diff --git a/lib/Support/YAMLTraits.cpp b/lib/Support/YAMLTraits.cpp
index f103ed8bcb..e2108e5b7a 100644
--- a/lib/Support/YAMLTraits.cpp
+++ b/lib/Support/YAMLTraits.cpp
@@ -41,10 +41,15 @@ void IO::setContext(void *Context) {
// Input
//===----------------------------------------------------------------------===//
-Input::Input(StringRef InputContent, void *Ctxt)
+Input::Input(StringRef InputContent,
+ void *Ctxt,
+ SourceMgr::DiagHandlerTy DiagHandler,
+ void *DiagHandlerCtxt)
: IO(Ctxt),
Strm(new Stream(InputContent, SrcMgr)),
CurrentNode(NULL) {
+ if (DiagHandler)
+ SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
DocIterator = Strm->begin();
}
@@ -55,10 +60,6 @@ error_code Input::error() {
return EC;
}
-void Input::setDiagHandler(SourceMgr::DiagHandlerTy Handler, void *Ctxt) {
- SrcMgr.setDiagHandler(Handler, Ctxt);
-}
-
bool Input::outputting() const {
return false;
}
@@ -66,6 +67,12 @@ bool Input::outputting() const {
bool Input::setCurrentDocument() {
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;
+ }
+
if (isa<NullNode>(N)) {
// Empty files are allowed and ignored
++DocIterator;
@@ -95,7 +102,8 @@ bool Input::mapTag(StringRef Tag, bool Default) {
void Input::beginMapping() {
if (EC)
return;
- MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
+ // CurrentNode can be null if the document is empty.
+ MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
if (MN) {
MN->ValidKeys.clear();
}
@@ -106,6 +114,15 @@ bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault,
UseDefault = false;
if (EC)
return false;
+
+ // CurrentNode is null for empty documents, which is an error in case required
+ // nodes are present.
+ if (!CurrentNode) {
+ if (Required)
+ EC = make_error_code(errc::invalid_argument);
+ return false;
+ }
+
MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
if (!MN) {
setError(CurrentNode, "not a mapping");
@@ -132,7 +149,8 @@ void Input::postflightKey(void *saveInfo) {
void Input::endMapping() {
if (EC)
return;
- MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
+ // CurrentNode can be null if the document is empty.
+ MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
if (!MN)
return;
for (MapHNode::NameToNode::iterator i = MN->Mapping.begin(),
@@ -273,6 +291,7 @@ void Input::scalarString(StringRef &S) {
}
void Input::setError(HNode *hnode, const Twine &message) {
+ assert(hnode && "HNode must not be NULL");
this->setError(hnode->_node, message);
}