diff options
Diffstat (limited to 'contrib/llvm/lib/Bitcode/Reader/BitstreamReader.cpp')
-rw-r--r-- | contrib/llvm/lib/Bitcode/Reader/BitstreamReader.cpp | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/contrib/llvm/lib/Bitcode/Reader/BitstreamReader.cpp b/contrib/llvm/lib/Bitcode/Reader/BitstreamReader.cpp index 5e3232e..a103fbd 100644 --- a/contrib/llvm/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/contrib/llvm/lib/Bitcode/Reader/BitstreamReader.cpp @@ -39,15 +39,16 @@ 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 + if (CurCodeSize > MaxChunkSize) + return true; + SkipToFourByteBoundary(); unsigned NumWords = Read(bitc::BlockSizeWidth); if (NumWordsP) *NumWordsP = NumWords; // Validate that this block is sane. - if (CurCodeSize == 0 || AtEndOfStream()) - return true; - - return false; + return CurCodeSize == 0 || AtEndOfStream(); } static uint64_t readAbbreviatedField(BitstreamCursor &Cursor, @@ -60,8 +61,10 @@ static uint64_t readAbbreviatedField(BitstreamCursor &Cursor, case BitCodeAbbrevOp::Blob: llvm_unreachable("Should not reach here"); case BitCodeAbbrevOp::Fixed: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.Read((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::VBR: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.ReadVBR64((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::Char6: return BitCodeAbbrevOp::DecodeChar6(Cursor.Read(6)); @@ -79,9 +82,11 @@ static void skipAbbreviatedField(BitstreamCursor &Cursor, case BitCodeAbbrevOp::Blob: llvm_unreachable("Should not reach here"); case BitCodeAbbrevOp::Fixed: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); Cursor.Read((unsigned)Op.getEncodingData()); break; case BitCodeAbbrevOp::VBR: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); Cursor.ReadVBR64((unsigned)Op.getEncodingData()); break; case BitCodeAbbrevOp::Char6: @@ -170,8 +175,12 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, unsigned Code; if (CodeOp.isLiteral()) Code = CodeOp.getLiteralValue(); - else + 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); + } for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) { const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); @@ -191,8 +200,15 @@ unsigned BitstreamCursor::readRecord(unsigned AbbrevID, unsigned NumElts = ReadVBR(6); // Get the element encoding. - assert(i+2 == e && "array op not second to last?"); + if (i + 2 != e) + report_fatal_error("Array op not second to last"); const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); + if (!EltEnc.isEncoding()) + report_fatal_error( + "Array element type has to be an encoding of a type"); + if (EltEnc.getEncoding() == BitCodeAbbrevOp::Array || + EltEnc.getEncoding() == BitCodeAbbrevOp::Blob) + report_fatal_error("Array element type can't be an Array or a Blob"); // Read all the elements. for (; NumElts; --NumElts) @@ -241,7 +257,7 @@ void BitstreamCursor::ReadAbbrevRecord() { BitCodeAbbrev *Abbv = new BitCodeAbbrev(); unsigned NumOpInfo = ReadVBR(5); for (unsigned i = 0; i != NumOpInfo; ++i) { - bool IsLiteral = Read(1) ? true : false; + bool IsLiteral = Read(1); if (IsLiteral) { Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); continue; @@ -249,7 +265,7 @@ void BitstreamCursor::ReadAbbrevRecord() { BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); if (BitCodeAbbrevOp::hasEncodingData(E)) { - unsigned Data = ReadVBR64(5); + uint64_t Data = ReadVBR64(5); // 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 @@ -260,10 +276,18 @@ void BitstreamCursor::ReadAbbrevRecord() { continue; } + if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) && + Data > MaxChunkSize) + report_fatal_error( + "Fixed or VBR abbrev record with size > MaxChunkData"); + Abbv->Add(BitCodeAbbrevOp(E, Data)); } else Abbv->Add(BitCodeAbbrevOp(E)); } + + if (Abbv->getNumOperandInfos() == 0) + report_fatal_error("Abbrev record with no operands"); CurAbbrevs.push_back(Abbv); } |