[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
This commit is contained in:
Reid Kleckner 2016-05-12 23:26:23 +00:00
parent 78a47bd1b4
commit 30e317fc1e
7 changed files with 29 additions and 15 deletions

View File

@ -78,7 +78,7 @@ public:
/// Visits the type records in Data. Sets the error flag on parse failures.
void visitTypeStream(ArrayRef<uint8_t> Data) {
for (const auto &I : makeTypeRange(Data)) {
for (const auto &I : makeTypeRange(Data, &HadError)) {
visitTypeRecord(I);
if (hadError())
break;

View File

@ -31,12 +31,12 @@ public:
ArrayRef<uint8_t> Data;
};
explicit RecordIterator(const ArrayRef<uint8_t> &RecordBytes)
: Data(RecordBytes), AtEnd(false) {
explicit RecordIterator(const ArrayRef<uint8_t> &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<uint8_t>.
if (Data.size() < sizeof(RecordPrefix))
return;
return parseError();
const auto *Rec = reinterpret_cast<const RecordPrefix *>(Data.data());
Data = Data.drop_front(sizeof(RecordPrefix));
Current.Length = Rec->RecordLen;
Current.Type = static_cast<Kind>(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<uint8_t> Data;
Record Current;
bool AtEnd;
@ -107,8 +116,8 @@ private:
template <typename Kind>
inline iterator_range<RecordIterator<Kind>>
makeRecordRange(ArrayRef<uint8_t> Data) {
return make_range(RecordIterator<Kind>(Data), RecordIterator<Kind>());
makeRecordRange(ArrayRef<uint8_t> Data, bool *HadError) {
return make_range(RecordIterator<Kind>(Data, HadError), RecordIterator<Kind>());
}
}
}

View File

@ -329,7 +329,7 @@ struct ThreadLocalDataSym {
typedef RecordIterator<SymbolRecordKind> SymbolIterator;
inline iterator_range<SymbolIterator> makeSymbolRange(ArrayRef<uint8_t> Data) {
return make_range(SymbolIterator(Data), SymbolIterator());
return make_range(SymbolIterator(Data, nullptr), SymbolIterator());
}
} // namespace codeview

View File

@ -27,8 +27,8 @@ namespace codeview {
typedef RecordIterator<TypeLeafKind> TypeIterator;
inline iterator_range<TypeIterator> makeTypeRange(ArrayRef<uint8_t> Data) {
return make_range(TypeIterator(Data), TypeIterator());
inline iterator_range<TypeIterator> makeTypeRange(ArrayRef<uint8_t> Data, bool *HadError) {
return make_range(TypeIterator(Data, HadError), TypeIterator());
}
} // end namespace codeview

View File

@ -38,7 +38,7 @@ public:
uint32_t TypeIndexEnd() const;
uint32_t NumTypeRecords() const;
iterator_range<codeview::TypeIterator> types() const;
iterator_range<codeview::TypeIterator> types(bool *HadError) const;
private:
PDBFile &Pdb;

View File

@ -129,6 +129,6 @@ uint32_t TpiStream::NumTypeRecords() const {
return TypeIndexEnd() - TypeIndexBegin();
}
iterator_range<codeview::TypeIterator> TpiStream::types() const {
return codeview::makeTypeRange(RecordsBuffer.data());
iterator_range<codeview::TypeIterator> TpiStream::types(bool *HadError) const {
return codeview::makeTypeRange(RecordsBuffer.data(), /*HadError=*/HadError);
}

View File

@ -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<RawError>(raw_error_code::corrupt_file,
"TPI stream contained corrupt record");
}
return Error::success();
}