From 3ab3fef2f17e35f1ab2a9bc6e28ddbc3fae27703 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Mon, 28 Nov 2016 21:38:52 +0000 Subject: [PATCH] Improve error handling in YAML parsing Some scanner errors were not checked and reported by the parser. Fix PR30934. Recommit r288014 after fixing unittest. Patch by: Serge Guelton Differential Revision: https://reviews.llvm.org/D26419 llvm-svn: 288071 --- llvm/include/llvm/Support/YAMLParser.h | 7 +++++-- llvm/lib/Support/YAMLParser.cpp | 32 ++++++++++++++++++++++---------- llvm/lib/Support/YAMLTraits.cpp | 11 ++++------- llvm/unittests/Support/YAMLIOTest.cpp | 8 ++++++++ 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/Support/YAMLParser.h b/llvm/include/llvm/Support/YAMLParser.h index dad6740..b9e3fa4 100644 --- a/llvm/include/llvm/Support/YAMLParser.h +++ b/llvm/include/llvm/Support/YAMLParser.h @@ -42,6 +42,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/SMLoc.h" #include +#include #include namespace llvm { @@ -75,9 +76,11 @@ std::string escape(StringRef Input); class Stream { public: /// \brief This keeps a reference to the string referenced by \p Input. - Stream(StringRef Input, SourceMgr &, bool ShowColors = true); + Stream(StringRef Input, SourceMgr &, bool ShowColors = true, + std::error_code *EC = nullptr); - Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true); + Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true, + std::error_code *EC = nullptr); ~Stream(); document_iterator begin(); diff --git a/llvm/lib/Support/YAMLParser.cpp b/llvm/lib/Support/YAMLParser.cpp index b74ea35..c17a6f6 100644 --- a/llvm/lib/Support/YAMLParser.cpp +++ b/llvm/lib/Support/YAMLParser.cpp @@ -232,8 +232,10 @@ namespace yaml { /// @brief Scans YAML tokens from a MemoryBuffer. class Scanner { public: - Scanner(StringRef Input, SourceMgr &SM, bool ShowColors = true); - Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors = true); + Scanner(StringRef Input, SourceMgr &SM, bool ShowColors = true, + std::error_code *EC = nullptr); + Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors = true, + std::error_code *EC = nullptr); /// @brief Parse the next token and return it without popping it. Token &peekNext(); @@ -250,6 +252,10 @@ public: if (Current >= End) Current = End - 1; + // propagate the error if possible + if (EC) + *EC = make_error_code(std::errc::invalid_argument); + // Don't print out more errors after the first one we encounter. The rest // are just the result of the first, and have no meaning. if (!Failed) @@ -528,6 +534,8 @@ private: /// @brief Potential simple keys. SmallVector SimpleKeys; + + std::error_code *EC; }; } // end namespace yaml @@ -722,13 +730,15 @@ std::string yaml::escape(StringRef Input) { return EscapedInput; } -Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors) - : SM(sm), ShowColors(ShowColors) { +Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors, + std::error_code *EC) + : SM(sm), ShowColors(ShowColors), EC(EC) { init(MemoryBufferRef(Input, "YAML")); } -Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors) - : SM(SM_), ShowColors(ShowColors) { +Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors, + std::error_code *EC) + : SM(SM_), ShowColors(ShowColors), EC(EC) { init(Buffer); } @@ -1726,11 +1736,13 @@ bool Scanner::fetchMoreTokens() { return false; } -Stream::Stream(StringRef Input, SourceMgr &SM, bool ShowColors) - : scanner(new Scanner(Input, SM, ShowColors)), CurrentDoc() {} +Stream::Stream(StringRef Input, SourceMgr &SM, bool ShowColors, + std::error_code *EC) + : scanner(new Scanner(Input, SM, ShowColors, EC)), CurrentDoc() {} -Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM, bool ShowColors) - : scanner(new Scanner(InputBuffer, SM, ShowColors)), CurrentDoc() {} +Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM, bool ShowColors, + std::error_code *EC) + : scanner(new Scanner(InputBuffer, SM, ShowColors, EC)), CurrentDoc() {} Stream::~Stream() {} diff --git a/llvm/lib/Support/YAMLTraits.cpp b/llvm/lib/Support/YAMLTraits.cpp index 75fac20..99d2070 100644 --- a/llvm/lib/Support/YAMLTraits.cpp +++ b/llvm/lib/Support/YAMLTraits.cpp @@ -44,13 +44,10 @@ void IO::setContext(void *Context) { // Input //===----------------------------------------------------------------------===// -Input::Input(StringRef InputContent, - void *Ctxt, - SourceMgr::DiagHandlerTy DiagHandler, - void *DiagHandlerCtxt) - : IO(Ctxt), - Strm(new Stream(InputContent, SrcMgr)), - CurrentNode(nullptr) { +Input::Input(StringRef InputContent, void *Ctxt, + SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt) + : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)), + CurrentNode(nullptr) { if (DiagHandler) SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); DocIterator = Strm->begin(); diff --git a/llvm/unittests/Support/YAMLIOTest.cpp b/llvm/unittests/Support/YAMLIOTest.cpp index bf70e74..c3e18d3 100644 --- a/llvm/unittests/Support/YAMLIOTest.cpp +++ b/llvm/unittests/Support/YAMLIOTest.cpp @@ -2368,3 +2368,11 @@ TEST(YAMLIO, TestMapWithContext) { out); out.clear(); } + +TEST(YAMLIO, InvalidInput) { + // polluting 1 value in the sequence + Input yin("---\n- foo: 3\n bar: 5\n1\n- foo: 3\n bar: 5\n...\n"); + std::vector Data; + yin >> Data; + EXPECT_TRUE((bool)yin.error()); +} -- 2.7.4