From 352f695def70b8cafbe5e53eb730c87f1211b123 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 2 Nov 2016 00:08:19 +0000 Subject: [PATCH] Bitcode: Change reader interface to take memory buffers. As proposed on llvm-dev: http://lists.llvm.org/pipermail/llvm-dev/2016-October/106595.html This change also fixes an API oddity where BitstreamCursor::Read() would return zero for the first read past the end of the bitstream, but would report_fatal_error for subsequent reads. Now we always report_fatal_error for all reads past the end. Updated clients to check for the end of the bitstream before reading from it. I also needed to add padding to the invalid bitcode tests in test/Bitcode/. This is because the streaming interface was not checking that the file size is a multiple of 4. Differential Revision: https://reviews.llvm.org/D26219 llvm-svn: 285773 --- include/llvm/Bitcode/BitstreamReader.h | 109 ++++++------------ include/llvm/Bitcode/ReaderWriter.h | 8 -- lib/Bitcode/Reader/BitcodeReader.cpp | 104 ++++------------- .../Inputs/invalid-array-operand-encoding.bc | Bin 579 -> 580 bytes test/Bitcode/Inputs/invalid-code-len-width.bc | Bin 173 -> 176 bytes .../Inputs/invalid-extractval-array-idx.bc | Bin 450 -> 452 bytes .../Inputs/invalid-function-comdat-id.bc | Bin 489 -> 492 bytes .../Inputs/invalid-fwdref-type-mismatch-2.bc | Bin 617 -> 620 bytes ...nvalid-metadata-not-followed-named-node.bc | Bin 878 -> 880 bytes .../Inputs/invalid-name-with-0-byte.bc | Bin 1265 -> 1268 bytes test/Bitcode/Inputs/invalid-unexpected-eof.bc | 2 +- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 8 +- tools/llvm-dis/llvm-dis.cpp | 39 ++----- unittests/Bitcode/BitReaderTest.cpp | 81 +------------ unittests/Bitcode/BitstreamReaderTest.cpp | 100 ++-------------- 15 files changed, 83 insertions(+), 368 deletions(-) diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index a3adb7bba28..8808935837a 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -15,13 +15,14 @@ #ifndef LLVM_BITCODE_BITSTREAMREADER_H #define LLVM_BITCODE_BITSTREAMREADER_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Bitcode/BitCodes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/StreamingMemoryObject.h" +#include "llvm/Support/MemoryBuffer.h" #include #include #include @@ -50,32 +51,25 @@ public: }; private: - std::unique_ptr BitcodeBytes; + ArrayRef BitcodeBytes; std::vector BlockInfoRecords; /// This is set to true if we don't care about the block/record name /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. - bool IgnoreBlockInfoNames; + bool IgnoreBlockInfoNames = true; public: - BitstreamReader() : IgnoreBlockInfoNames(true) { - } + BitstreamReader() = default; + BitstreamReader(ArrayRef BitcodeBytes) + : BitcodeBytes(BitcodeBytes) {} + BitstreamReader(StringRef BitcodeBytes) + : BitcodeBytes(reinterpret_cast(BitcodeBytes.data()), + BitcodeBytes.size()) {} + BitstreamReader(MemoryBufferRef BitcodeBytes) + : BitstreamReader(BitcodeBytes.getBuffer()) {} - BitstreamReader(const unsigned char *Start, const unsigned char *End) - : IgnoreBlockInfoNames(true) { - init(Start, End); - } - - BitstreamReader(std::unique_ptr BitcodeBytes) - : BitcodeBytes(std::move(BitcodeBytes)), IgnoreBlockInfoNames(true) {} - - void init(const unsigned char *Start, const unsigned char *End) { - assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); - BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); - } - - MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } + ArrayRef getBitcodeBytes() { return BitcodeBytes; } /// This is called by clients that want block/record name information. void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; } @@ -131,9 +125,6 @@ class SimpleBitstreamCursor { BitstreamReader *R = nullptr; size_t NextChar = 0; - // The size of the bicode. 0 if we don't know it yet. - size_t Size = 0; - public: /// This is the current data we have pulled from the stream but have not /// returned to the client. This is specifically and intentionally defined to @@ -159,17 +150,11 @@ public: bool canSkipToPos(size_t pos) const { // pos can be skipped to if it is a valid address or one byte past the end. - return pos == 0 || - R->getBitcodeBytes().isValidAddress(static_cast(pos - 1)); + return pos <= R->getBitcodeBytes().size(); } bool AtEndOfStream() { - if (BitsInCurWord != 0) - return false; - if (Size != 0) - return Size <= NextChar; - fillCurWord(); - return BitsInCurWord == 0; + return BitsInCurWord == 0 && R->getBitcodeBytes().size() <= NextChar; } /// Return the bit # of the bit we are reading. @@ -218,7 +203,7 @@ public: /// Get a pointer into the bitstream at the specified byte offset. const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) { - return R->getBitcodeBytes().getPointer(ByteNo, NumBytes); + return R->getBitcodeBytes().data() + ByteNo; } /// Get a pointer into the bitstream at the specified bit offset. @@ -230,26 +215,25 @@ public: } void fillCurWord() { - if (Size != 0 && NextChar >= Size) + ArrayRef Buf = R->getBitcodeBytes(); + if (NextChar >= Buf.size()) report_fatal_error("Unexpected end of file"); // Read the next word from the stream. - uint8_t Array[sizeof(word_t)] = {0}; - - uint64_t BytesRead = - R->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar); - - // If we run out of data, stop at the end of the stream. - if (BytesRead == 0) { + const uint8_t *NextCharPtr = Buf.data() + NextChar; + unsigned BytesRead; + if (Buf.size() >= NextChar + sizeof(word_t)) { + BytesRead = sizeof(word_t); + CurWord = + support::endian::read( + NextCharPtr); + } else { + // Short read. + BytesRead = Buf.size() - NextChar; CurWord = 0; - BitsInCurWord = 0; - Size = NextChar; - return; + for (unsigned B = 0; B != BytesRead; ++B) + CurWord |= NextCharPtr[B] << (B * 8); } - - CurWord = - support::endian::read( - Array); NextChar += BytesRead; BitsInCurWord = BytesRead * 8; } @@ -278,9 +262,9 @@ public: fillCurWord(); - // If we run out of data, stop at the end of the stream. + // If we run out of data, abort. if (BitsLeft > BitsInCurWord) - return 0; + report_fatal_error("Unexpected end of file"); word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); @@ -346,31 +330,7 @@ public: } /// Skip to the end of the file. - void skipToEnd() { NextChar = R->getBitcodeBytes().getExtent(); } - - /// Prevent the cursor from reading past a byte boundary. - /// - /// Prevent the cursor from requesting byte reads past \c Limit. This is - /// useful when working with a cursor on a StreamingMemoryObject, when it's - /// desirable to avoid invalidating the result of getPointerToByte(). - /// - /// If \c Limit is on a word boundary, AtEndOfStream() will return true if - /// the cursor position reaches or exceeds \c Limit, regardless of the true - /// number of available bytes. Otherwise, AtEndOfStream() returns true when - /// it reaches or exceeds the next word boundary. - void setArtificialByteLimit(uint64_t Limit) { - assert(getCurrentByteNo() < Limit && "Move cursor before lowering limit"); - - // Round to word boundary. - Limit = alignTo(Limit, sizeof(word_t)); - - // Only change size if the new one is lower. - if (!Size || Size > Limit) - Size = Limit; - } - - /// Return the Size, if known. - uint64_t getSizeIfKnown() const { return Size; } + void skipToEnd() { NextChar = R->getBitcodeBytes().size(); } }; /// When advancing through a bitstream cursor, each advance can discover a few @@ -470,6 +430,9 @@ public: /// Advance the current bitstream, returning the next entry in the stream. BitstreamEntry advance(unsigned Flags = 0) { while (true) { + if (AtEndOfStream()) + return BitstreamEntry::getError(); + unsigned Code = ReadCode(); if (Code == bitc::END_BLOCK) { // Pop the end of the block unless Flags tells us not to. diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 0ff32d86956..178dbda0789 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -24,7 +24,6 @@ namespace llvm { class BitstreamWriter; - class DataStreamer; class LLVMContext; class Module; class ModulePass; @@ -47,13 +46,6 @@ namespace llvm { LLVMContext &Context, bool ShouldLazyLoadMetadata = false); - /// Read the header of the specified stream and prepare for lazy - /// deserialization and streaming of function bodies. - ErrorOr> - getStreamedBitcodeModule(StringRef Name, - std::unique_ptr Streamer, - LLVMContext &Context); - /// Read the header of the specified bitcode buffer and extract just the /// triple information. If successful, this returns a string. On error, this /// returns "". diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index f224b046d70..710187af951 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -61,14 +61,12 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/DataStream.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/StreamingMemoryObject.h" #include #include #include @@ -232,29 +230,19 @@ private: class BitcodeReaderBase { protected: - BitcodeReaderBase() = default; BitcodeReaderBase(MemoryBuffer *Buffer) : Buffer(Buffer) {} std::unique_ptr Buffer; std::unique_ptr StreamFile; BitstreamCursor Stream; - std::error_code initStream(std::unique_ptr Streamer); - std::error_code initStreamFromBuffer(); - std::error_code initLazyStream(std::unique_ptr Streamer); + std::error_code initStream(); virtual std::error_code error(const Twine &Message) = 0; virtual ~BitcodeReaderBase() = default; }; -std::error_code -BitcodeReaderBase::initStream(std::unique_ptr Streamer) { - if (Streamer) - return initLazyStream(std::move(Streamer)); - return initStreamFromBuffer(); -} - -std::error_code BitcodeReaderBase::initStreamFromBuffer() { +std::error_code BitcodeReaderBase::initStream() { const unsigned char *BufPtr = (const unsigned char*)Buffer->getBufferStart(); const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize(); @@ -267,39 +255,12 @@ std::error_code BitcodeReaderBase::initStreamFromBuffer() { if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true)) return error("Invalid bitcode wrapper header"); - StreamFile.reset(new BitstreamReader(BufPtr, BufEnd)); + StreamFile.reset(new BitstreamReader(ArrayRef(BufPtr, BufEnd))); Stream.init(&*StreamFile); return std::error_code(); } -std::error_code -BitcodeReaderBase::initLazyStream(std::unique_ptr Streamer) { - // Check and strip off the bitcode wrapper; BitstreamReader expects never to - // see it. - auto OwnedBytes = - llvm::make_unique(std::move(Streamer)); - StreamingMemoryObject &Bytes = *OwnedBytes; - StreamFile = llvm::make_unique(std::move(OwnedBytes)); - Stream.init(&*StreamFile); - - unsigned char buf[16]; - if (Bytes.readBytes(buf, 16, 0) != 16) - return error("Invalid bitcode signature"); - - if (!isBitcode(buf, buf + 16)) - return error("Invalid bitcode signature"); - - if (isBitcodeWrapper(buf, buf + 4)) { - const unsigned char *bitcodeStart = buf; - const unsigned char *bitcodeEnd = buf + 16; - SkipBitcodeWrapperHeader(bitcodeStart, bitcodeEnd, false); - Bytes.dropLeadingBytes(bitcodeStart - buf); - Bytes.setKnownObjectSize(bitcodeEnd - bitcodeStart); - } - return std::error_code(); -} - class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { LLVMContext &Context; Module *TheModule = nullptr; @@ -399,7 +360,6 @@ public: std::error_code error(const Twine &Message) override; BitcodeReader(MemoryBuffer *Buffer, LLVMContext &Context); - BitcodeReader(LLVMContext &Context); ~BitcodeReader() override { freeState(); } std::error_code materializeForwardReferencedFunctions(); @@ -414,8 +374,7 @@ public: /// \brief Main interface to parsing a bitcode buffer. /// \returns true if an error occurred. - std::error_code parseBitcodeInto(std::unique_ptr Streamer, - Module *M, + std::error_code parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata = false); /// \brief Cheap mechanism to just extract module triple @@ -638,8 +597,7 @@ public: /// \brief Main interface to parsing a bitcode buffer. /// \returns true if an error occurred. - std::error_code parseSummaryIndexInto(std::unique_ptr Streamer, - ModuleSummaryIndex *I); + std::error_code parseSummaryIndexInto(ModuleSummaryIndex *I); private: std::error_code parseModule(); @@ -706,9 +664,6 @@ BitcodeReader::BitcodeReader(MemoryBuffer *Buffer, LLVMContext &Context) : BitcodeReaderBase(Buffer), Context(Context), ValueList(Context), MetadataList(Context) {} -BitcodeReader::BitcodeReader(LLVMContext &Context) - : Context(Context), ValueList(Context), MetadataList(Context) {} - std::error_code BitcodeReader::materializeForwardReferencedFunctions() { if (WillMaterializeAllForwardRefs) return std::error_code(); @@ -2166,10 +2121,6 @@ std::error_code BitcodeReader::parseMetadataStrings(ArrayRef Record, SimpleBitstreamCursor R(*StreamFile); R.jumpToPointer(Lengths.begin()); - // Ensure that Blob doesn't get invalidated, even if this is reading from - // a StreamingMemoryObject with corrupt data. - R.setArtificialByteLimit(R.getCurrentByteNo() + StringsOffset); - StringRef Strings = Blob.drop_front(StringsOffset); do { if (R.AtEndOfStream()) @@ -4203,12 +4154,11 @@ static bool hasValidBitcodeHeader(BitstreamCursor &Stream) { return true; } -std::error_code -BitcodeReader::parseBitcodeInto(std::unique_ptr Streamer, - Module *M, bool ShouldLazyLoadMetadata) { +std::error_code BitcodeReader::parseBitcodeInto(Module *M, + bool ShouldLazyLoadMetadata) { TheModule = M; - if (std::error_code EC = initStream(std::move(Streamer))) + if (std::error_code EC = initStream()) return EC; // Sniff for the signature. @@ -4282,7 +4232,7 @@ ErrorOr BitcodeReader::parseModuleTriple() { } ErrorOr BitcodeReader::parseTriple() { - if (std::error_code EC = initStream(nullptr)) + if (std::error_code EC = initStream()) return EC; // Sniff for the signature. @@ -4317,7 +4267,7 @@ ErrorOr BitcodeReader::parseTriple() { } ErrorOr BitcodeReader::parseIdentificationBlock() { - if (std::error_code EC = initStream(nullptr)) + if (std::error_code EC = initStream()) return EC; // Sniff for the signature. @@ -4367,7 +4317,7 @@ std::error_code BitcodeReader::parseGlobalObjectAttachment( } ErrorOr BitcodeReader::hasObjCCategory() { - if (std::error_code EC = initStream(nullptr)) + if (std::error_code EC = initStream()) return EC; // Sniff for the signature. @@ -5955,7 +5905,8 @@ std::error_code ModuleSummaryIndexBitcodeReader::error(const Twine &Message) { ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader( MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler, bool CheckGlobalValSummaryPresenceOnly) - : BitcodeReaderBase(Buffer), DiagnosticHandler(std::move(DiagnosticHandler)), + : BitcodeReaderBase(Buffer), + DiagnosticHandler(std::move(DiagnosticHandler)), CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {} void ModuleSummaryIndexBitcodeReader::freeState() { Buffer = nullptr; } @@ -6555,11 +6506,11 @@ std::error_code ModuleSummaryIndexBitcodeReader::parseModuleStringTable() { } // Parse the function info index from the bitcode streamer into the given index. -std::error_code ModuleSummaryIndexBitcodeReader::parseSummaryIndexInto( - std::unique_ptr Streamer, ModuleSummaryIndex *I) { +std::error_code +ModuleSummaryIndexBitcodeReader::parseSummaryIndexInto(ModuleSummaryIndex *I) { TheIndex = I; - if (std::error_code EC = initStream(std::move(Streamer))) + if (std::error_code EC = initStream()) return EC; // Sniff for the signature. @@ -6624,8 +6575,7 @@ const std::error_category &llvm::BitcodeErrorCategory() { //===----------------------------------------------------------------------===// static ErrorOr> -getBitcodeModuleImpl(std::unique_ptr Streamer, StringRef Name, - BitcodeReader *R, LLVMContext &Context, +getBitcodeModuleImpl(StringRef Name, BitcodeReader *R, LLVMContext &Context, bool MaterializeAll, bool ShouldLazyLoadMetadata) { std::unique_ptr M = llvm::make_unique(Name, Context); M->setMaterializer(R); @@ -6636,8 +6586,7 @@ getBitcodeModuleImpl(std::unique_ptr Streamer, StringRef Name, }; // Delay parsing Metadata if ShouldLazyLoadMetadata is true. - if (std::error_code EC = R->parseBitcodeInto(std::move(Streamer), M.get(), - ShouldLazyLoadMetadata)) + if (std::error_code EC = R->parseBitcodeInto(M.get(), ShouldLazyLoadMetadata)) return cleanupOnError(EC); if (MaterializeAll) { @@ -6667,7 +6616,7 @@ getLazyBitcodeModuleImpl(std::unique_ptr &&Buffer, BitcodeReader *R = new BitcodeReader(Buffer.get(), Context); ErrorOr> Ret = - getBitcodeModuleImpl(nullptr, Buffer->getBufferIdentifier(), R, Context, + getBitcodeModuleImpl(Buffer->getBufferIdentifier(), R, Context, MaterializeAll, ShouldLazyLoadMetadata); if (!Ret) return Ret; @@ -6683,17 +6632,6 @@ llvm::getLazyBitcodeModule(std::unique_ptr &&Buffer, ShouldLazyLoadMetadata); } -ErrorOr> -llvm::getStreamedBitcodeModule(StringRef Name, - std::unique_ptr Streamer, - LLVMContext &Context) { - std::unique_ptr M = llvm::make_unique(Name, Context); - BitcodeReader *R = new BitcodeReader(Context); - - return getBitcodeModuleImpl(std::move(Streamer), Name, R, Context, false, - false); -} - ErrorOr> llvm::parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context) { std::unique_ptr Buf = MemoryBuffer::getMemBuffer(Buffer, false); @@ -6746,7 +6684,7 @@ ErrorOr> llvm::getModuleSummaryIndex( return EC; }; - if (std::error_code EC = R.parseSummaryIndexInto(nullptr, Index.get())) + if (std::error_code EC = R.parseSummaryIndexInto(Index.get())) return cleanupOnError(EC); Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now. @@ -6765,7 +6703,7 @@ bool llvm::hasGlobalValueSummary( return false; }; - if (std::error_code EC = R.parseSummaryIndexInto(nullptr, nullptr)) + if (std::error_code EC = R.parseSummaryIndexInto(nullptr)) return cleanupOnError(EC); Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now. diff --git a/test/Bitcode/Inputs/invalid-array-operand-encoding.bc b/test/Bitcode/Inputs/invalid-array-operand-encoding.bc index f7ec2eb700a32055c43837b58e2c94144976b25a..2256fce555d4c151dec66a29b4300f72641c03f0 100644 GIT binary patch delta 9 QcmX@ia)f1rGZP~N01*5Fh5!Hn delta 7 OcmX@Ya+qaxPfuPT4n|Y1^^Q&0-yi@ delta 6 NcmdnMxR!CkS^x;I0-XQ= diff --git a/test/Bitcode/Inputs/invalid-extractval-array-idx.bc b/test/Bitcode/Inputs/invalid-extractval-array-idx.bc index 7465df361c0557e284b7c1388bd194493df00b7b..7234e0d6daabe2134423a0562e50b0601d9ae2e5 100644 GIT binary patch delta 10 RcmX@ae1v(!Ax0(!1^^Y}0|Ed5 delta 7 OcmX@Ye296&Aw~cU-~#{v diff --git a/test/Bitcode/Inputs/invalid-function-comdat-id.bc b/test/Bitcode/Inputs/invalid-function-comdat-id.bc index d0ad8234bc869b0992c925e4db2442724f66bf30..11e024120d208f7011594c86cb2147cbe4e6c003 100644 GIT binary patch delta 11 ScmaFK{DyhMOGah}1_l5e=L2~F delta 7 OcmaFE{E~UYOGW?>2?KTj diff --git a/test/Bitcode/Inputs/invalid-fwdref-type-mismatch-2.bc b/test/Bitcode/Inputs/invalid-fwdref-type-mismatch-2.bc index 8e38340eedea20ee424501a3217b4980fd350548..41011f76ce8c5a85b88ccf21e21af3360af1ed4e 100644 GIT binary patch delta 11 ScmaFK@`hzYCKEFQ0|NjV{sQ~} delta 7 OcmaFE@{(mkCKCV-6ax7G diff --git a/test/Bitcode/Inputs/invalid-metadata-not-followed-named-node.bc b/test/Bitcode/Inputs/invalid-metadata-not-followed-named-node.bc index 42a2c3e65fecb9d56daa43ef548231050f386510..dbd8933fd2f245f6869465348156d51ba9c1dd03 100644 GIT binary patch delta 10 RcmaFI_JM6f9y1dI0{|C}0}cQH delta 7 Ocmeys_Ks~s9y0(AXafuY diff --git a/test/Bitcode/Inputs/invalid-name-with-0-byte.bc b/test/Bitcode/Inputs/invalid-name-with-0-byte.bc index 9c6a9158eee7f1bf05c9b67bb10cb1f0881defbb..c38e363c24ba8848c8d4d83b78297e4ae957b971 100644 GIT binary patch delta 11 Scmey!`Gs@CM;2xV1_l5gG6SFh delta 7 Ocmeyu`H^$OM-~7NxC5O4 diff --git a/test/Bitcode/Inputs/invalid-unexpected-eof.bc b/test/Bitcode/Inputs/invalid-unexpected-eof.bc index a487393d066..02a22e44082 100644 --- a/test/Bitcode/Inputs/invalid-unexpected-eof.bc +++ b/test/Bitcode/Inputs/invalid-unexpected-eof.bc @@ -1 +1 @@ -BCÀÞ! 000000 00000000000000 \ No newline at end of file +BCÀÞ! 000000 000000000000000 \ No newline at end of file diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 96820f9c8a0..fec11e35d50 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -436,10 +436,6 @@ static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent, SimpleBitstreamCursor R(Reader); R.jumpToPointer(Lengths.begin()); - // Ensure that Blob doesn't get invalidated, even if this is reading from a - // StreamingMemoryObject with corrupt data. - R.setArtificialByteLimit(R.getCurrentByteNo() + StringsOffset); - StringRef Strings = Blob.drop_front(StringsOffset); do { if (R.AtEndOfStream()) @@ -735,7 +731,7 @@ static bool openBitcodeFile(StringRef Path, return ReportError("Invalid bitcode wrapper header"); } - StreamFile = BitstreamReader(BufPtr, EndBufPtr); + StreamFile = BitstreamReader(ArrayRef(BufPtr, EndBufPtr)); Stream = BitstreamCursor(StreamFile); StreamFile.CollectBlockInfoNames(); @@ -814,7 +810,7 @@ static int AnalyzeBitcode() { if (Dump) outs() << "\n\n"; - uint64_t BufferSizeBits = StreamFile.getBitcodeBytes().getExtent() * CHAR_BIT; + uint64_t BufferSizeBits = StreamFile.getBitcodeBytes().size() * CHAR_BIT; // Print a summary of the read file. outs() << "Summary of " << InputFilename << ":\n"; outs() << " Total size: "; diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index 88333aeb688..69533ccac52 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -26,7 +26,6 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/DataStream.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormattedStream.h" @@ -139,34 +138,20 @@ static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) { } static Expected> openInputFile(LLVMContext &Context) { - if (MaterializeMetadata) { - ErrorOr> MBOrErr = - MemoryBuffer::getFileOrSTDIN(InputFilename); - if (!MBOrErr) - return errorCodeToError(MBOrErr.getError()); - ErrorOr> MOrErr = - getLazyBitcodeModule(std::move(*MBOrErr), Context, - /*ShouldLazyLoadMetadata=*/true); - if (!MOrErr) - return errorCodeToError(MOrErr.getError()); + ErrorOr> MBOrErr = + MemoryBuffer::getFileOrSTDIN(InputFilename); + if (!MBOrErr) + return errorCodeToError(MBOrErr.getError()); + ErrorOr> MOrErr = + getLazyBitcodeModule(std::move(*MBOrErr), Context, + /*ShouldLazyLoadMetadata=*/true); + if (!MOrErr) + return errorCodeToError(MOrErr.getError()); + if (MaterializeMetadata) (*MOrErr)->materializeMetadata(); - return std::move(*MOrErr); - } else { - std::string ErrorMessage; - std::unique_ptr Streamer = - getDataFileStreamer(InputFilename, &ErrorMessage); - if (!Streamer) - return make_error(ErrorMessage, inconvertibleErrorCode()); - std::string DisplayFilename; - if (InputFilename == "-") - DisplayFilename = ""; - else - DisplayFilename = InputFilename; - ErrorOr> MOrErr = - getStreamedBitcodeModule(DisplayFilename, std::move(Streamer), Context); + else (*MOrErr)->materializeAll(); - return std::move(*MOrErr); - } + return std::move(*MOrErr); } int main(int argc, char **argv) { diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp index d0f33d12d5b..e4b90cc6855 100644 --- a/unittests/Bitcode/BitReaderTest.cpp +++ b/unittests/Bitcode/BitReaderTest.cpp @@ -18,11 +18,9 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/Support/DataStream.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/StreamingMemoryObject.h" #include "gtest/gtest.h" using namespace llvm; @@ -62,84 +60,6 @@ static std::unique_ptr getLazyModuleFromAssembly(LLVMContext &Context, return std::move(ModuleOrErr.get()); } -class BufferDataStreamer : public DataStreamer { - std::unique_ptr Buffer; - unsigned Pos = 0; - size_t GetBytes(unsigned char *Out, size_t Len) override { - StringRef Buf = Buffer->getBuffer(); - size_t Left = Buf.size() - Pos; - Len = std::min(Left, Len); - memcpy(Out, Buffer->getBuffer().substr(Pos).data(), Len); - Pos += Len; - return Len; - } - -public: - BufferDataStreamer(std::unique_ptr Buffer) - : Buffer(std::move(Buffer)) {} -}; - -static std::unique_ptr -getStreamedModuleFromAssembly(LLVMContext &Context, SmallString<1024> &Mem, - const char *Assembly) { - writeModuleToBuffer(parseAssembly(Context, Assembly), Mem); - std::unique_ptr Buffer = - MemoryBuffer::getMemBuffer(Mem.str(), "test", false); - auto Streamer = llvm::make_unique(std::move(Buffer)); - ErrorOr> ModuleOrErr = - getStreamedBitcodeModule("test", std::move(Streamer), Context); - return std::move(ModuleOrErr.get()); -} - -// Checks if we correctly detect eof if we try to read N bits when there are not -// enough bits left on the input stream to read N bits, and we are using a data -// streamer. In particular, it checks if we properly set the object size when -// the eof is reached under such conditions. -TEST(BitReaderTest, TestForEofAfterReadFailureOnDataStreamer) { - // Note: Because StreamingMemoryObject does a call to method GetBytes in it's - // constructor, using internal constant kChunkSize, we must fill the input - // with more characters than that amount. - static size_t InputSize = StreamingMemoryObject::kChunkSize + 5; - char *Text = new char[InputSize]; - std::memset(Text, 'a', InputSize); - Text[InputSize - 1] = '\0'; - StringRef Input(Text); - - // Build bitsteam reader using data streamer. - auto MemoryBuf = MemoryBuffer::getMemBuffer(Input); - std::unique_ptr Streamer( - new BufferDataStreamer(std::move(MemoryBuf))); - auto OwnedBytes = - llvm::make_unique(std::move(Streamer)); - auto Reader = llvm::make_unique(std::move(OwnedBytes)); - BitstreamCursor Cursor; - Cursor.init(Reader.get()); - - // Jump to two bytes before end of stream. - Cursor.JumpToBit((InputSize - 4) * CHAR_BIT); - // Try to read 4 bytes when only 2 are present, resulting in error value 0. - const size_t ReadErrorValue = 0; - EXPECT_EQ(ReadErrorValue, Cursor.Read(32)); - // Should be at eof now. - EXPECT_TRUE(Cursor.AtEndOfStream()); - - delete[] Text; -} - -TEST(BitReaderTest, MateralizeForwardRefWithStream) { - SmallString<1024> Mem; - - LLVMContext Context; - std::unique_ptr M = getStreamedModuleFromAssembly( - Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" - "define void @func() {\n" - " unreachable\n" - "bb:\n" - " unreachable\n" - "}\n"); - EXPECT_FALSE(M->getFunction("func")->empty()); -} - // Tests that lazy evaluation can parse functions out of order. TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) { SmallString<1024> Mem; @@ -216,6 +136,7 @@ TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 " unreachable\n" "}\n"); EXPECT_FALSE(verifyModule(*M, &dbgs())); + EXPECT_FALSE(M->getFunction("func")->empty()); } TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { diff --git a/unittests/Bitcode/BitstreamReaderTest.cpp b/unittests/Bitcode/BitstreamReaderTest.cpp index 2be774cc539..b5bd4a6fb5a 100644 --- a/unittests/Bitcode/BitstreamReaderTest.cpp +++ b/unittests/Bitcode/BitstreamReaderTest.cpp @@ -10,33 +10,17 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/StreamingMemoryObject.h" #include "gtest/gtest.h" using namespace llvm; namespace { -class BufferStreamer : public DataStreamer { - StringRef Buffer; - -public: - BufferStreamer(StringRef Buffer) : Buffer(Buffer) {} - size_t GetBytes(unsigned char *OutBuffer, size_t Length) override { - if (Length >= Buffer.size()) - Length = Buffer.size(); - - std::copy(Buffer.begin(), Buffer.begin() + Length, OutBuffer); - Buffer = Buffer.drop_front(Length); - return Length; - } -}; - TEST(BitstreamReaderTest, AtEndOfStream) { uint8_t Bytes[4] = { 0x00, 0x01, 0x02, 0x03 }; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamReader Reader(Bytes); BitstreamCursor Cursor(Reader); EXPECT_FALSE(Cursor.AtEndOfStream()); @@ -56,7 +40,7 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) { uint8_t Bytes[4] = { 0x00, 0x01, 0x02, 0x03 }; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamReader Reader(Bytes); BitstreamCursor Cursor(Reader); Cursor.JumpToBit(32); @@ -64,8 +48,7 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) { } TEST(BitstreamReaderTest, AtEndOfStreamEmpty) { - uint8_t Dummy = 0xFF; - BitstreamReader Reader(&Dummy, &Dummy); + BitstreamReader Reader(ArrayRef{}); BitstreamCursor Cursor(Reader); EXPECT_TRUE(Cursor.AtEndOfStream()); @@ -73,10 +56,10 @@ TEST(BitstreamReaderTest, AtEndOfStreamEmpty) { TEST(BitstreamReaderTest, getCurrentByteNo) { uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03}; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamReader Reader(Bytes); SimpleBitstreamCursor Cursor(Reader); - for (unsigned I = 0, E = 33; I != E; ++I) { + for (unsigned I = 0, E = 32; I != E; ++I) { EXPECT_EQ(I / 8, Cursor.getCurrentByteNo()); (void)Cursor.Read(1); } @@ -85,7 +68,7 @@ TEST(BitstreamReaderTest, getCurrentByteNo) { TEST(BitstreamReaderTest, getPointerToByte) { uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamReader Reader(Bytes); SimpleBitstreamCursor Cursor(Reader); for (unsigned I = 0, E = 8; I != E; ++I) { @@ -95,7 +78,7 @@ TEST(BitstreamReaderTest, getPointerToByte) { TEST(BitstreamReaderTest, getPointerToBit) { uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamReader Reader(Bytes); SimpleBitstreamCursor Cursor(Reader); for (unsigned I = 0, E = 8; I != E; ++I) { @@ -105,7 +88,7 @@ TEST(BitstreamReaderTest, getPointerToBit) { TEST(BitstreamReaderTest, jumpToPointer) { uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamReader Reader(Bytes); SimpleBitstreamCursor Cursor(Reader); for (unsigned I : {0, 6, 2, 7}) { @@ -114,68 +97,6 @@ TEST(BitstreamReaderTest, jumpToPointer) { } } -TEST(BitstreamReaderTest, setArtificialByteLimit) { - uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); - SimpleBitstreamCursor Cursor(Reader); - - Cursor.setArtificialByteLimit(8); - EXPECT_EQ(8u, Cursor.getSizeIfKnown()); - while (!Cursor.AtEndOfStream()) - (void)Cursor.Read(1); - - EXPECT_EQ(8u, Cursor.getCurrentByteNo()); -} - -TEST(BitstreamReaderTest, setArtificialByteLimitNotWordBoundary) { - uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); - SimpleBitstreamCursor Cursor(Reader); - - Cursor.setArtificialByteLimit(5); - EXPECT_EQ(8u, Cursor.getSizeIfKnown()); - while (!Cursor.AtEndOfStream()) - (void)Cursor.Read(1); - - EXPECT_EQ(8u, Cursor.getCurrentByteNo()); -} - -TEST(BitstreamReaderTest, setArtificialByteLimitPastTheEnd) { - uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b}; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); - SimpleBitstreamCursor Cursor(Reader); - - // The size of the memory object isn't known yet. Set it too high and - // confirm that we don't read too far. - Cursor.setArtificialByteLimit(24); - EXPECT_EQ(24u, Cursor.getSizeIfKnown()); - while (!Cursor.AtEndOfStream()) - (void)Cursor.Read(1); - - EXPECT_EQ(12u, Cursor.getCurrentByteNo()); - EXPECT_EQ(12u, Cursor.getSizeIfKnown()); -} - -TEST(BitstreamReaderTest, setArtificialByteLimitPastTheEndKnown) { - uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b}; - BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); - SimpleBitstreamCursor Cursor(Reader); - - // Save the size of the memory object in the cursor. - while (!Cursor.AtEndOfStream()) - (void)Cursor.Read(1); - EXPECT_EQ(12u, Cursor.getCurrentByteNo()); - EXPECT_EQ(12u, Cursor.getSizeIfKnown()); - - Cursor.setArtificialByteLimit(20); - EXPECT_TRUE(Cursor.AtEndOfStream()); - EXPECT_EQ(12u, Cursor.getSizeIfKnown()); -} - TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) { SmallVector BlobData; for (unsigned I = 0, E = 1024; I != E; ++I) @@ -208,9 +129,8 @@ TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) { } // Stream the buffer into the reader. - BitstreamReader R(llvm::make_unique( - llvm::make_unique( - StringRef(Buffer.begin(), Buffer.size())))); + BitstreamReader R( + ArrayRef((const uint8_t *)Buffer.begin(), Buffer.size())); BitstreamCursor Stream(R); // Header. Included in test so that we can run llvm-bcanalyzer to debug