diff options
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitstreamReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitstreamReader.cpp | 273 |
1 files changed, 197 insertions, 76 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitstreamReader.cpp b/llvm/lib/Bitcode/Reader/BitstreamReader.cpp index 985944738cb..2f29ce29db0 100644 --- a/llvm/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitstreamReader.cpp @@ -17,9 +17,8 @@ using namespace llvm; // BitstreamCursor implementation //===----------------------------------------------------------------------===// -/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter -/// the block, and return true if the block has an error. -bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { +/// Having read the ENTER_SUBBLOCK abbrevid, enter the block. +Error BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { // Save the current block's state on BlockScope. BlockScope.push_back(Block(CurCodeSize)); BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); @@ -34,21 +33,39 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { } // Get the codesize of this block. - CurCodeSize = ReadVBR(bitc::CodeLenWidth); - // We can't read more than MaxChunkSize at a time + Expected<uint32_t> MaybeVBR = ReadVBR(bitc::CodeLenWidth); + if (!MaybeVBR) + return MaybeVBR.takeError(); + CurCodeSize = MaybeVBR.get(); + if (CurCodeSize > MaxChunkSize) - return true; + return llvm::createStringError( + std::errc::illegal_byte_sequence, + "can't read more than %zu at a time, trying to read %u", +MaxChunkSize, + CurCodeSize); SkipToFourByteBoundary(); - unsigned NumWords = Read(bitc::BlockSizeWidth); - if (NumWordsP) *NumWordsP = NumWords; - - // Validate that this block is sane. - return CurCodeSize == 0 || AtEndOfStream(); + Expected<word_t> MaybeNum = Read(bitc::BlockSizeWidth); + if (!MaybeNum) + return MaybeNum.takeError(); + word_t NumWords = MaybeNum.get(); + if (NumWordsP) + *NumWordsP = NumWords; + + if (CurCodeSize == 0) + return llvm::createStringError( + std::errc::illegal_byte_sequence, + "can't enter sub-block: current code size is 0"); + if (AtEndOfStream()) + return llvm::createStringError( + std::errc::illegal_byte_sequence, + "can't enter sub block: already at end of stream"); + + return Error::success(); } -static uint64_t readAbbreviatedField(BitstreamCursor &Cursor, - const BitCodeAbbrevOp &Op) { +static Expected<uint64_t> readAbbreviatedField(BitstreamCursor &Cursor, + const BitCodeAbbrevOp &Op) { assert(!Op.isLiteral() && "Not to be used with literals!"); // Decode the value as we are commanded. @@ -63,13 +80,16 @@ static uint64_t readAbbreviatedField(BitstreamCursor &Cursor, assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.ReadVBR64((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::Char6: - return BitCodeAbbrevOp::DecodeChar6(Cursor.Read(6)); + if (Expected<unsigned> Res = Cursor.Read(6)) + return BitCodeAbbrevOp::DecodeChar6(Res.get()); + else + return Res.takeError(); } llvm_unreachable("invalid abbreviation encoding"); } -static void skipAbbreviatedField(BitstreamCursor &Cursor, - const BitCodeAbbrevOp &Op) { +static Error skipAbbreviatedField(BitstreamCursor &Cursor, + const BitCodeAbbrevOp &Op) { assert(!Op.isLiteral() && "Not to be used with literals!"); // Decode the value as we are commanded. @@ -79,26 +99,43 @@ static void skipAbbreviatedField(BitstreamCursor &Cursor, llvm_unreachable("Should not reach here"); case BitCodeAbbrevOp::Fixed: assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); - Cursor.Read((unsigned)Op.getEncodingData()); - break; + if (Expected<unsigned> Res = Cursor.Read((unsigned)Op.getEncodingData())) + break; + else + return Res.takeError(); case BitCodeAbbrevOp::VBR: assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); - Cursor.ReadVBR64((unsigned)Op.getEncodingData()); - break; + if (Expected<uint64_t> Res = + Cursor.ReadVBR64((unsigned)Op.getEncodingData())) + break; + else + return Res.takeError(); case BitCodeAbbrevOp::Char6: - Cursor.Read(6); - break; + if (Expected<unsigned> Res = Cursor.Read(6)) + break; + else + return Res.takeError(); } + return ErrorSuccess(); } /// skipRecord - Read the current record and discard it. -unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) { +Expected<unsigned> BitstreamCursor::skipRecord(unsigned AbbrevID) { // Skip unabbreviated records by reading past their entries. if (AbbrevID == bitc::UNABBREV_RECORD) { - unsigned Code = ReadVBR(6); - unsigned NumElts = ReadVBR(6); + Expected<uint32_t> MaybeCode = ReadVBR(6); + if (!MaybeCode) + return MaybeCode.takeError(); + unsigned Code = MaybeCode.get(); + Expected<uint32_t> MaybeVBR = ReadVBR(6); + if (!MaybeVBR) + return MaybeVBR.get(); + unsigned NumElts = MaybeVBR.get(); for (unsigned i = 0; i != NumElts; ++i) - (void)ReadVBR64(6); + if (Expected<uint64_t> Res = ReadVBR64(6)) + ; // Skip! + else + return Res.takeError(); return Code; } @@ -110,8 +147,13 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) { else { if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array || CodeOp.getEncoding() == BitCodeAbbrevOp::Blob) - report_fatal_error("Abbreviation starts with an Array or a Blob"); - Code = readAbbreviatedField(*this, CodeOp); + return llvm::createStringError( + std::errc::illegal_byte_sequence, + "Abbreviation starts with an Array or a Blob"); + Expected<uint64_t> MaybeCode = readAbbreviatedField(*this, CodeOp); + if (!MaybeCode) + return MaybeCode.takeError(); + Code = MaybeCode.get(); } for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e; ++i) { @@ -121,13 +163,17 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) { if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { - skipAbbreviatedField(*this, Op); + if (Error Err = skipAbbreviatedField(*this, Op)) + return std::move(Err); continue; } if (Op.getEncoding() == BitCodeAbbrevOp::Array) { // Array case. Read the number of elements as a vbr6. - unsigned NumElts = ReadVBR(6); + Expected<uint32_t> MaybeNum = ReadVBR(6); + if (!MaybeNum) + return MaybeNum.takeError(); + unsigned NumElts = MaybeNum.get(); // Get the element encoding. assert(i+2 == e && "array op not second to last?"); @@ -140,15 +186,22 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) { report_fatal_error("Array element type can't be an Array or a Blob"); case BitCodeAbbrevOp::Fixed: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); - JumpToBit(GetCurrentBitNo() + NumElts * EltEnc.getEncodingData()); + if (Error Err = JumpToBit(GetCurrentBitNo() + + NumElts * EltEnc.getEncodingData())) + return std::move(Err); break; case BitCodeAbbrevOp::VBR: assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize); for (; NumElts; --NumElts) - ReadVBR64((unsigned)EltEnc.getEncodingData()); + if (Expected<uint64_t> Res = + ReadVBR64((unsigned)EltEnc.getEncodingData())) + ; // Skip! + else + return Res.takeError(); break; case BitCodeAbbrevOp::Char6: - JumpToBit(GetCurrentBitNo() + NumElts * 6); + if (Error Err = JumpToBit(GetCurrentBitNo() + NumElts * 6)) + return std::move(Err); break; } continue; @@ -156,7 +209,10 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) { assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. - unsigned NumElts = ReadVBR(6); + Expected<uint32_t> MaybeNum = ReadVBR(6); + if (!MaybeNum) + return MaybeNum.takeError(); + unsigned NumElts = MaybeNum.get(); SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. @@ -170,19 +226,30 @@ unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) { } // Skip over the blob. - JumpToBit(NewEnd); + if (Error Err = JumpToBit(NewEnd)) + return std::move(Err); } return Code; } -unsigned BitstreamCursor::readRecord(unsigned AbbrevID, - SmallVectorImpl<uint64_t> &Vals, - StringRef *Blob) { +Expected<unsigned> BitstreamCursor::readRecord(unsigned AbbrevID, + SmallVectorImpl<uint64_t> &Vals, + StringRef *Blob) { if (AbbrevID == bitc::UNABBREV_RECORD) { - unsigned Code = ReadVBR(6); - unsigned NumElts = ReadVBR(6); + Expected<uint32_t> MaybeCode = ReadVBR(6); + if (!MaybeCode) + return MaybeCode.takeError(); + uint32_t Code = MaybeCode.get(); + Expected<uint32_t> MaybeNumElts = ReadVBR(6); + if (!MaybeNumElts) + return MaybeNumElts.takeError(); + uint32_t NumElts = MaybeNumElts.get(); + for (unsigned i = 0; i != NumElts; ++i) - Vals.push_back(ReadVBR64(6)); + if (Expected<uint64_t> MaybeVal = ReadVBR64(6)) + Vals.push_back(MaybeVal.get()); + else + return MaybeVal.takeError(); return Code; } @@ -198,7 +265,10 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array || CodeOp.getEncoding() == BitCodeAbbrevOp::Blob) report_fatal_error("Abbreviation starts with an Array or a Blob"); - Code = readAbbreviatedField(*this, CodeOp); + if (Expected<uint64_t> MaybeCode = readAbbreviatedField(*this, CodeOp)) + Code = MaybeCode.get(); + else + return MaybeCode.takeError(); } for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { @@ -210,13 +280,19 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, if (Op.getEncoding() != BitCodeAbbrevOp::Array && Op.getEncoding() != BitCodeAbbrevOp::Blob) { - Vals.push_back(readAbbreviatedField(*this, Op)); + if (Expected<uint64_t> MaybeVal = readAbbreviatedField(*this, Op)) + Vals.push_back(MaybeVal.get()); + else + return MaybeVal.takeError(); continue; } if (Op.getEncoding() == BitCodeAbbrevOp::Array) { // Array case. Read the number of elements as a vbr6. - unsigned NumElts = ReadVBR(6); + Expected<uint32_t> MaybeNumElts = ReadVBR(6); + if (!MaybeNumElts) + return MaybeNumElts.takeError(); + uint32_t NumElts = MaybeNumElts.get(); // Get the element encoding. if (i + 2 != e) @@ -232,22 +308,36 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, report_fatal_error("Array element type can't be an Array or a Blob"); case BitCodeAbbrevOp::Fixed: for (; NumElts; --NumElts) - Vals.push_back(Read((unsigned)EltEnc.getEncodingData())); + if (Expected<SimpleBitstreamCursor::word_t> MaybeVal = + Read((unsigned)EltEnc.getEncodingData())) + Vals.push_back(MaybeVal.get()); + else + return MaybeVal.takeError(); break; case BitCodeAbbrevOp::VBR: for (; NumElts; --NumElts) - Vals.push_back(ReadVBR64((unsigned)EltEnc.getEncodingData())); + if (Expected<uint64_t> MaybeVal = + ReadVBR64((unsigned)EltEnc.getEncodingData())) + Vals.push_back(MaybeVal.get()); + else + return MaybeVal.takeError(); break; case BitCodeAbbrevOp::Char6: for (; NumElts; --NumElts) - Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6))); + if (Expected<SimpleBitstreamCursor::word_t> MaybeVal = Read(6)) + Vals.push_back(BitCodeAbbrevOp::DecodeChar6(MaybeVal.get())); + else + return MaybeVal.takeError(); } continue; } assert(Op.getEncoding() == BitCodeAbbrevOp::Blob); // Blob case. Read the number of bytes as a vbr6. - unsigned NumElts = ReadVBR(6); + Expected<uint32_t> MaybeNumElts = ReadVBR(6); + if (!MaybeNumElts) + return MaybeNumElts.takeError(); + uint32_t NumElts = MaybeNumElts.get(); SkipToFourByteBoundary(); // 32-bit alignment // Figure out where the end of this blob will be including tail padding. @@ -265,7 +355,8 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, // Otherwise, inform the streamer that we need these bytes in memory. Skip // over tail padding first, in case jumping to NewEnd invalidates the Blob // pointer. - JumpToBit(NewEnd); + if (Error Err = JumpToBit(NewEnd)) + return std::move(Err); const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts); // If we can return a reference to the data, do so to avoid copying it. @@ -281,19 +372,35 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, return Code; } -void BitstreamCursor::ReadAbbrevRecord() { +Error BitstreamCursor::ReadAbbrevRecord() { auto Abbv = std::make_shared<BitCodeAbbrev>(); - unsigned NumOpInfo = ReadVBR(5); + Expected<uint32_t> MaybeNumOpInfo = ReadVBR(5); + if (!MaybeNumOpInfo) + return MaybeNumOpInfo.takeError(); + unsigned NumOpInfo = MaybeNumOpInfo.get(); for (unsigned i = 0; i != NumOpInfo; ++i) { - bool IsLiteral = Read(1); + Expected<word_t> MaybeIsLiteral = Read(1); + if (!MaybeIsLiteral) + return MaybeIsLiteral.takeError(); + bool IsLiteral = MaybeIsLiteral.get(); if (IsLiteral) { - Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); + Expected<uint64_t> MaybeOp = ReadVBR64(8); + if (!MaybeOp) + return MaybeOp.takeError(); + Abbv->Add(BitCodeAbbrevOp(MaybeOp.get())); continue; } - BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); + Expected<word_t> MaybeEncoding = Read(3); + if (!MaybeEncoding) + return MaybeEncoding.takeError(); + BitCodeAbbrevOp::Encoding E = + (BitCodeAbbrevOp::Encoding)MaybeEncoding.get(); if (BitCodeAbbrevOp::hasEncodingData(E)) { - uint64_t Data = ReadVBR64(5); + Expected<uint64_t> MaybeData = ReadVBR64(5); + if (!MaybeData) + return MaybeData.takeError(); + uint64_t Data = MaybeData.get(); // As a special case, handle fixed(0) (i.e., a fixed field with zero bits) // and vbr(0) as a literal zero. This is decoded the same way, and avoids @@ -317,11 +424,14 @@ void BitstreamCursor::ReadAbbrevRecord() { if (Abbv->getNumOperandInfos() == 0) report_fatal_error("Abbrev record with no operands"); CurAbbrevs.push_back(std::move(Abbv)); + + return Error::success(); } -Optional<BitstreamBlockInfo> +Expected<Optional<BitstreamBlockInfo>> BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { - if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return None; + if (llvm::Error Err = EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) + return std::move(Err); BitstreamBlockInfo NewBlockInfo; @@ -330,7 +440,11 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { // Read all the records for this module. while (true) { - BitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs); + Expected<BitstreamEntry> MaybeEntry = + advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs); + if (!MaybeEntry) + return MaybeEntry.takeError(); + BitstreamEntry Entry = MaybeEntry.get(); switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: // Handled for us already. @@ -346,7 +460,8 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { // Read abbrev records, associate them with CurBID. if (Entry.ID == bitc::DEFINE_ABBREV) { if (!CurBlockInfo) return None; - ReadAbbrevRecord(); + if (Error Err = ReadAbbrevRecord()) + return std::move(Err); // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the // appropriate BlockInfo. @@ -357,22 +472,28 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { // Read a record. Record.clear(); - switch (readRecord(Entry.ID, Record)) { - default: break; // Default behavior, ignore unknown content. - case bitc::BLOCKINFO_CODE_SETBID: - if (Record.size() < 1) return None; - CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]); - break; - case bitc::BLOCKINFO_CODE_BLOCKNAME: { - if (!CurBlockInfo) return None; - if (!ReadBlockInfoNames) - break; // Ignore name. - std::string Name; - for (unsigned i = 0, e = Record.size(); i != e; ++i) - Name += (char)Record[i]; - CurBlockInfo->Name = Name; - break; - } + Expected<unsigned> MaybeBlockInfo = readRecord(Entry.ID, Record); + if (!MaybeBlockInfo) + return MaybeBlockInfo.takeError(); + switch (MaybeBlockInfo.get()) { + default: + break; // Default behavior, ignore unknown content. + case bitc::BLOCKINFO_CODE_SETBID: + if (Record.size() < 1) + return None; + CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]); + break; + case bitc::BLOCKINFO_CODE_BLOCKNAME: { + if (!CurBlockInfo) + return None; + if (!ReadBlockInfoNames) + break; // Ignore name. + std::string Name; + for (unsigned i = 0, e = Record.size(); i != e; ++i) + Name += (char)Record[i]; + CurBlockInfo->Name = Name; + break; + } case bitc::BLOCKINFO_CODE_SETRECORDNAME: { if (!CurBlockInfo) return None; if (!ReadBlockInfoNames) @@ -384,6 +505,6 @@ BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) { Name)); break; } - } + } } } |