forked from OSchip/llvm-project
[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
This commit is contained in:
parent
0ba164bbcb
commit
5baa2bc2e1
|
@ -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; }
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue