Index: llvm/trunk/include/llvm/Bitstream/BitstreamReader.h =================================================================== --- llvm/trunk/include/llvm/Bitstream/BitstreamReader.h +++ llvm/trunk/include/llvm/Bitstream/BitstreamReader.h @@ -294,6 +294,9 @@ BitsInCurWord = 0; } + /// Return the size of the stream in bytes. + size_t SizeInBytes() const { return BitcodeBytes.size(); } + /// Skip to the end of the file. void skipToEnd() { NextChar = BitcodeBytes.size(); } }; @@ -364,17 +367,18 @@ explicit BitstreamCursor(MemoryBufferRef BitcodeBytes) : SimpleBitstreamCursor(BitcodeBytes) {} - using SimpleBitstreamCursor::canSkipToPos; using SimpleBitstreamCursor::AtEndOfStream; + using SimpleBitstreamCursor::canSkipToPos; + using SimpleBitstreamCursor::fillCurWord; using SimpleBitstreamCursor::getBitcodeBytes; using SimpleBitstreamCursor::GetCurrentBitNo; using SimpleBitstreamCursor::getCurrentByteNo; using SimpleBitstreamCursor::getPointerToByte; using SimpleBitstreamCursor::JumpToBit; - using SimpleBitstreamCursor::fillCurWord; using SimpleBitstreamCursor::Read; using SimpleBitstreamCursor::ReadVBR; using SimpleBitstreamCursor::ReadVBR64; + using SimpleBitstreamCursor::SizeInBytes; /// Return the number of bits used to encode an abbrev #. unsigned getAbbrevIDWidth() const { return CurCodeSize; } Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -858,7 +858,7 @@ StringRef ProducerIdentification, LLVMContext &Context) : BitcodeReaderBase(std::move(Stream), Strtab), Context(Context), - ValueList(Context) { + ValueList(Context, Stream.SizeInBytes()) { this->ProducerIdentification = ProducerIdentification; } Index: llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp +++ llvm/trunk/lib/Bitcode/Reader/MetadataLoader.cpp @@ -130,8 +130,15 @@ LLVMContext &Context; + /// Maximum number of valid references. Forward references exceeding the + /// maximum must be invalid. + unsigned RefsUpperBound; + public: - BitcodeReaderMetadataList(LLVMContext &C) : Context(C) {} + BitcodeReaderMetadataList(LLVMContext &C, size_t RefsUpperBound) + : Context(C), + RefsUpperBound(std::min((size_t)std::numeric_limits::max(), + RefsUpperBound)) {} // vector compatibility methods unsigned size() const { return MetadataPtrs.size(); } @@ -218,6 +225,10 @@ } Metadata *BitcodeReaderMetadataList::getMetadataFwdRef(unsigned Idx) { + // Bail out for a clearly invalid value. + if (Idx >= RefsUpperBound) + return nullptr; + if (Idx >= size()) resize(Idx + 1); @@ -625,9 +636,10 @@ BitcodeReaderValueList &ValueList, std::function getTypeByID, bool IsImporting) - : MetadataList(TheModule.getContext()), ValueList(ValueList), - Stream(Stream), Context(TheModule.getContext()), TheModule(TheModule), - getTypeByID(std::move(getTypeByID)), IsImporting(IsImporting) {} + : MetadataList(TheModule.getContext(), Stream.SizeInBytes()), + ValueList(ValueList), Stream(Stream), Context(TheModule.getContext()), + TheModule(TheModule), getTypeByID(std::move(getTypeByID)), + IsImporting(IsImporting) {} Error parseMetadata(bool ModuleLevel); Index: llvm/trunk/lib/Bitcode/Reader/ValueList.h =================================================================== --- llvm/trunk/lib/Bitcode/Reader/ValueList.h +++ llvm/trunk/lib/Bitcode/Reader/ValueList.h @@ -46,8 +46,15 @@ ResolveConstantsTy ResolveConstants; LLVMContext &Context; + /// Maximum number of valid references. Forward references exceeding the + /// maximum must be invalid. + unsigned RefsUpperBound; + public: - BitcodeReaderValueList(LLVMContext &C) : Context(C) {} + BitcodeReaderValueList(LLVMContext &C, size_t RefsUpperBound) + : Context(C), + RefsUpperBound(std::min((size_t)std::numeric_limits::max(), + RefsUpperBound)) {} ~BitcodeReaderValueList() { assert(ResolveConstants.empty() && "Constants not resolved?"); Index: llvm/trunk/lib/Bitcode/Reader/ValueList.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/ValueList.cpp +++ llvm/trunk/lib/Bitcode/Reader/ValueList.cpp @@ -97,6 +97,10 @@ } Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) { + // Bail out for a clearly invalid value. + if (Idx >= RefsUpperBound) + return nullptr; + if (Idx >= size()) resize(Idx + 1); @@ -114,8 +118,8 @@ Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty, Type **FullTy) { - // Bail out for a clearly invalid value. This would make us call resize(0) - if (Idx == std::numeric_limits::max()) + // Bail out for a clearly invalid value. + if (Idx >= RefsUpperBound) return nullptr; if (Idx >= size()) Index: llvm/trunk/test/Bitcode/pr18704.ll =================================================================== --- llvm/trunk/test/Bitcode/pr18704.ll +++ llvm/trunk/test/Bitcode/pr18704.ll @@ -1,6 +1,6 @@ ; RUN: not llvm-dis < %s.bc 2>&1 | FileCheck %s -; CHECK: llvm-dis{{(\.EXE|\.exe)?}}: error: Never resolved value found in function +; CHECK: llvm-dis{{(\.EXE|\.exe)?}}: error: Invalid record ; pr18704.ll.bc has an instruction referring to invalid type. ; The test checks that LLVM reports the error and doesn't access freed memory