Index: llvm/trunk/include/llvm/Bitcode/BitcodeReader.h =================================================================== --- llvm/trunk/include/llvm/Bitcode/BitcodeReader.h +++ llvm/trunk/include/llvm/Bitcode/BitcodeReader.h @@ -42,6 +42,7 @@ /// Represents a module in a bitcode file. class BitcodeModule { + // This covers the identification (if present) and module blocks. ArrayRef Buffer; StringRef ModuleIdentifier; Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2306,7 +2306,10 @@ assert(GO); } - uint64_t FuncWordOffset = Record[1]; + // Note that we subtract 1 here because the offset is relative to one word + // before the start of the identification or module block, which was + // historically always the start of the regular bitcode header. + uint64_t FuncWordOffset = Record[1] - 1; Function *F = dyn_cast(GO); assert(F); uint64_t FuncBitOffset = FuncWordOffset * 32; @@ -4354,7 +4357,10 @@ case bitc::MODULE_CODE_VSTOFFSET: if (Record.size() < 1) return error("Invalid record"); - VSTOffset = Record[0]; + // Note that we subtract 1 here because the offset is relative to one word + // before the start of the identification or module block, which was + // historically always the start of the regular bitcode header. + VSTOffset = Record[0] - 1; break; /// MODULE_CODE_SOURCE_FILENAME: [namechar x N] case bitc::MODULE_CODE_SOURCE_FILENAME: @@ -6549,13 +6555,14 @@ return StreamOrErr.takeError(); BitstreamCursor &Stream = *StreamOrErr; - uint64_t IdentificationBit = -1ull; std::vector Modules; while (true) { + uint64_t BCBegin = Stream.getCurrentByteNo(); + // We may be consuming bitcode from a client that leaves garbage at the end // of the bitcode stream (e.g. Apple's ar tool). If we are close enough to // the end that there cannot possibly be another module, stop looking. - if (Stream.getCurrentByteNo() + 8 >= Stream.getBitcodeBytes().size()) + if (BCBegin + 8 >= Stream.getBitcodeBytes().size()) return Modules; BitstreamEntry Entry = Stream.advance(); @@ -6564,17 +6571,35 @@ case BitstreamEntry::Error: return error("Malformed block"); - case BitstreamEntry::SubBlock: - if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) - IdentificationBit = Stream.GetCurrentBitNo(); - else if (Entry.ID == bitc::MODULE_BLOCK_ID) - Modules.push_back({Stream.getBitcodeBytes(), + case BitstreamEntry::SubBlock: { + uint64_t IdentificationBit = -1ull; + if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) { + IdentificationBit = Stream.GetCurrentBitNo() - BCBegin * 8; + if (Stream.SkipBlock()) + return error("Malformed block"); + + Entry = Stream.advance(); + if (Entry.Kind != BitstreamEntry::SubBlock || + Entry.ID != bitc::MODULE_BLOCK_ID) + return error("Malformed block"); + } + + if (Entry.ID == bitc::MODULE_BLOCK_ID) { + uint64_t ModuleBit = Stream.GetCurrentBitNo() - BCBegin * 8; + if (Stream.SkipBlock()) + return error("Malformed block"); + + Modules.push_back({Stream.getBitcodeBytes().slice( + BCBegin, Stream.getCurrentByteNo() - BCBegin), Buffer.getBufferIdentifier(), IdentificationBit, - Stream.GetCurrentBitNo()}); + ModuleBit}); + continue; + } if (Stream.SkipBlock()) return error("Malformed block"); continue; + } case BitstreamEntry::Record: Stream.skipRecord(Entry.ID); continue;