diff options
author | David Majnemer <david.majnemer@gmail.com> | 2016-04-28 23:24:23 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2016-04-28 23:24:23 +0000 |
commit | 5baa2bc2e146ebf09a0c9d5bdaf82ab6d01144bc (patch) | |
tree | 74028d51242634606eb4059f02734710c3389df2 /llvm/lib/DebugInfo | |
parent | 0ba164bbcba92404f2f8df7ee4129f2b059776a1 (diff) | |
download | bcm5719-llvm-5baa2bc2e146ebf09a0c9d5bdaf82ab6d01144bc.tar.gz bcm5719-llvm-5baa2bc2e146ebf09a0c9d5bdaf82ab6d01144bc.zip |
[llvm-pdbdump] Correctly read data larger than a block
A bug was introduced when the code was refactored which resulted in a
bad memory access.
This fixes PR27565.
llvm-svn: 267953
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBStream.cpp | 40 |
1 files changed, 15 insertions, 25 deletions
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBStream.cpp index 7146f4d11a2..6db04a55970 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBStream.cpp @@ -13,9 +13,9 @@ using namespace llvm; PDBStream::PDBStream(uint32_t StreamIdx, const PDBFile &File) : Pdb(File) { - this->StreamLength = Pdb.getStreamByteSize(StreamIdx); - this->BlockList = Pdb.getStreamBlockList(StreamIdx); - this->Offset = 0; + StreamLength = Pdb.getStreamByteSize(StreamIdx); + BlockList = Pdb.getStreamBlockList(StreamIdx); + Offset = 0; } std::error_code PDBStream::readInteger(uint32_t &Dest) { @@ -41,34 +41,20 @@ std::error_code PDBStream::readBytes(void *Dest, uint32_t Length) { uint32_t OffsetInBlock = Offset % Pdb.getBlockSize(); // Make sure we aren't trying to read beyond the end of the stream. - if (this->Offset + Length > this->StreamLength) + if (Length > StreamLength) + return std::make_error_code(std::errc::bad_address); + if (Offset > StreamLength - Length) return std::make_error_code(std::errc::bad_address); - // Modify the passed in offset to point to the data after the object. - Offset += Length; - - // Handle the contiguous case: the offset + size stays within a block. - if (OffsetInBlock + Length <= Pdb.getBlockSize()) { - uint32_t StreamBlockAddr = this->BlockList[BlockNum]; - - StringRef Data = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize()); - ::memcpy(Dest, Data.data() + OffsetInBlock, Length); - return std::error_code(); - } - - // The non-contiguous case: we will stitch together non-contiguous chunks uint32_t BytesLeft = Length; uint32_t BytesWritten = 0; char *WriteBuffer = static_cast<char *>(Dest); while (BytesLeft > 0) { - uint32_t StreamBlockAddr = this->BlockList[BlockNum]; - uint64_t StreamBlockOffset = - PDBFile::blockToOffset(StreamBlockAddr, Pdb.getBlockSize()) + - OffsetInBlock; + uint32_t StreamBlockAddr = BlockList[BlockNum]; StringRef Data = Pdb.getBlockData(StreamBlockAddr, Pdb.getBlockSize()); - const char *ChunkStart = Data.data() + StreamBlockOffset; + const char *ChunkStart = Data.data() + OffsetInBlock; uint32_t BytesInChunk = std::min(BytesLeft, Pdb.getBlockSize() - OffsetInBlock); ::memcpy(WriteBuffer + BytesWritten, ChunkStart, BytesInChunk); @@ -78,11 +64,15 @@ std::error_code PDBStream::readBytes(void *Dest, uint32_t Length) { ++BlockNum; OffsetInBlock = 0; } + + // Modify the offset to point to the data after the object. + Offset += Length; + return std::error_code(); } -void PDBStream::setOffset(uint32_t O) { this->Offset = O; } +void PDBStream::setOffset(uint32_t O) { Offset = O; } -uint32_t PDBStream::getOffset() const { return this->Offset; } +uint32_t PDBStream::getOffset() const { return Offset; } -uint32_t PDBStream::getLength() const { return this->StreamLength; } +uint32_t PDBStream::getLength() const { return StreamLength; } |