summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-04-28 23:24:23 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-04-28 23:24:23 +0000
commit5baa2bc2e146ebf09a0c9d5bdaf82ab6d01144bc (patch)
tree74028d51242634606eb4059f02734710c3389df2 /llvm/lib/DebugInfo
parent0ba164bbcba92404f2f8df7ee4129f2b059776a1 (diff)
downloadbcm5719-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.cpp40
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; }
OpenPOWER on IntegriCloud