From 30e317fc1ef6c10cb9ad22fa00fa72a943238411 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 12 May 2016 23:26:23 +0000 Subject: [PATCH] [codeview] Try to handle errors better in record iterator git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269381 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../llvm/DebugInfo/CodeView/CVTypeVisitor.h | 2 +- .../llvm/DebugInfo/CodeView/RecordIterator.h | 23 +++++++++++++------ .../llvm/DebugInfo/CodeView/SymbolRecord.h | 2 +- include/llvm/DebugInfo/CodeView/TypeStream.h | 4 ++-- include/llvm/DebugInfo/PDB/Raw/TpiStream.h | 2 +- lib/DebugInfo/PDB/Raw/TpiStream.cpp | 4 ++-- tools/llvm-pdbdump/llvm-pdbdump.cpp | 7 +++++- 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index bab18f247d0..95473dd0c83 100644 --- a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -78,7 +78,7 @@ public: /// Visits the type records in Data. Sets the error flag on parse failures. void visitTypeStream(ArrayRef Data) { - for (const auto &I : makeTypeRange(Data)) { + for (const auto &I : makeTypeRange(Data, &HadError)) { visitTypeRecord(I); if (hadError()) break; diff --git a/include/llvm/DebugInfo/CodeView/RecordIterator.h b/include/llvm/DebugInfo/CodeView/RecordIterator.h index f2ed8d26173..f5ef7de3ddd 100644 --- a/include/llvm/DebugInfo/CodeView/RecordIterator.h +++ b/include/llvm/DebugInfo/CodeView/RecordIterator.h @@ -31,12 +31,12 @@ public: ArrayRef Data; }; - explicit RecordIterator(const ArrayRef &RecordBytes) - : Data(RecordBytes), AtEnd(false) { + explicit RecordIterator(const ArrayRef &RecordBytes, bool *HadError) + : HadError(HadError), Data(RecordBytes), AtEnd(false) { next(); // Prime the pump } - RecordIterator() : AtEnd(true) {} + RecordIterator() : HadError(nullptr), AtEnd(true) {} // For iterators to compare equal, they must both point at the same record // in the same data stream, or they must both be at the end of a stream. @@ -82,13 +82,16 @@ private: // FIXME: Use consumeObject when it deals in ArrayRef. if (Data.size() < sizeof(RecordPrefix)) - return; + return parseError(); const auto *Rec = reinterpret_cast(Data.data()); Data = Data.drop_front(sizeof(RecordPrefix)); Current.Length = Rec->RecordLen; Current.Type = static_cast(uint16_t(Rec->RecordKind)); - Current.Data = Data.slice(0, Current.Length - 2); + size_t RecLen = Current.Length - 2; + if (RecLen > Data.size()) + return parseError(); + Current.Data = Data.slice(0, RecLen); // The next record starts immediately after this one. Data = Data.drop_front(Current.Data.size()); @@ -100,6 +103,12 @@ private: return; } + void parseError() { + if (HadError) + *HadError = true; + } + + bool *HadError; ArrayRef Data; Record Current; bool AtEnd; @@ -107,8 +116,8 @@ private: template inline iterator_range> -makeRecordRange(ArrayRef Data) { - return make_range(RecordIterator(Data), RecordIterator()); +makeRecordRange(ArrayRef Data, bool *HadError) { + return make_range(RecordIterator(Data, HadError), RecordIterator()); } } } diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h index fc8cf904b84..2999b95248f 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -329,7 +329,7 @@ struct ThreadLocalDataSym { typedef RecordIterator SymbolIterator; inline iterator_range makeSymbolRange(ArrayRef Data) { - return make_range(SymbolIterator(Data), SymbolIterator()); + return make_range(SymbolIterator(Data, nullptr), SymbolIterator()); } } // namespace codeview diff --git a/include/llvm/DebugInfo/CodeView/TypeStream.h b/include/llvm/DebugInfo/CodeView/TypeStream.h index 1998d10090d..c1370d889c8 100644 --- a/include/llvm/DebugInfo/CodeView/TypeStream.h +++ b/include/llvm/DebugInfo/CodeView/TypeStream.h @@ -27,8 +27,8 @@ namespace codeview { typedef RecordIterator TypeIterator; -inline iterator_range makeTypeRange(ArrayRef Data) { - return make_range(TypeIterator(Data), TypeIterator()); +inline iterator_range makeTypeRange(ArrayRef Data, bool *HadError) { + return make_range(TypeIterator(Data, HadError), TypeIterator()); } } // end namespace codeview diff --git a/include/llvm/DebugInfo/PDB/Raw/TpiStream.h b/include/llvm/DebugInfo/PDB/Raw/TpiStream.h index 7681b124280..ac7c7978e34 100644 --- a/include/llvm/DebugInfo/PDB/Raw/TpiStream.h +++ b/include/llvm/DebugInfo/PDB/Raw/TpiStream.h @@ -38,7 +38,7 @@ public: uint32_t TypeIndexEnd() const; uint32_t NumTypeRecords() const; - iterator_range types() const; + iterator_range types(bool *HadError) const; private: PDBFile &Pdb; diff --git a/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/lib/DebugInfo/PDB/Raw/TpiStream.cpp index fd0d0eb2c40..db2ea20ce14 100644 --- a/lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ b/lib/DebugInfo/PDB/Raw/TpiStream.cpp @@ -129,6 +129,6 @@ uint32_t TpiStream::NumTypeRecords() const { return TypeIndexEnd() - TypeIndexBegin(); } -iterator_range TpiStream::types() const { - return codeview::makeTypeRange(RecordsBuffer.data()); +iterator_range TpiStream::types(bool *HadError) const { + return codeview::makeTypeRange(RecordsBuffer.data(), /*HadError=*/HadError); } diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp index 62016d2d389..748bccfe9de 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -44,6 +44,7 @@ #include "llvm/DebugInfo/PDB/Raw/ModStream.h" #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/DebugInfo/PDB/Raw/RawError.h" #include "llvm/DebugInfo/PDB/Raw/RawSession.h" #include "llvm/DebugInfo/PDB/Raw/StreamReader.h" #include "llvm/DebugInfo/PDB/Raw/TpiStream.h" @@ -376,7 +377,8 @@ static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File) { ListScope L(P, "Records"); codeview::CVTypeDumper TD(P, false); - for (auto &Type : Tpi.types()) { + bool HadError = false; + for (auto &Type : Tpi.types(&HadError)) { DictScope DD(P, ""); if (opts::DumpTpiRecords) @@ -385,6 +387,9 @@ static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File) { if (opts::DumpTpiRecordBytes) P.printBinaryBlock("Bytes", Type.Data); } + if (HadError) + return make_error(raw_error_code::corrupt_file, + "TPI stream contained corrupt record"); } return Error::success(); }