Disk: Fix out of bounds accesses in base ReadDriver
parent
f8bfb243fa
commit
80cd4ae052
|
|
@ -14,19 +14,21 @@ optional<uint64_t> DiskReadDriver::readLogicalDisk(Communication& com, device_ev
|
||||||
|
|
||||||
const uint32_t idealBlockSize = getBlockSizeBounds().second;
|
const uint32_t idealBlockSize = getBlockSizeBounds().second;
|
||||||
const uint64_t startBlock = pos / idealBlockSize;
|
const uint64_t startBlock = pos / idealBlockSize;
|
||||||
const uint64_t posWithinFirstBlock = pos % idealBlockSize;
|
const uint32_t posWithinFirstBlock = static_cast<uint32_t>(pos % idealBlockSize);
|
||||||
const uint64_t blocks = amount / idealBlockSize + (amount % idealBlockSize ? 1 : 0) + (posWithinFirstBlock ? 1 : 0);
|
uint64_t blocks = amount / idealBlockSize + (amount % idealBlockSize ? 1 : 0);
|
||||||
|
if(blocks * idealBlockSize - posWithinFirstBlock < amount)
|
||||||
|
blocks++; // We need one more block to get the last partial block's worth
|
||||||
uint64_t blocksProcessed = 0;
|
uint64_t blocksProcessed = 0;
|
||||||
|
|
||||||
while(blocksProcessed < blocks && timeout >= std::chrono::milliseconds::zero()) {
|
while(blocksProcessed < blocks && timeout >= std::chrono::milliseconds::zero()) {
|
||||||
const uint64_t currentBlock = startBlock + blocksProcessed;
|
const uint64_t currentBlock = startBlock + blocksProcessed;
|
||||||
|
|
||||||
const int intoOffset = std::min<int>((blocksProcessed * idealBlockSize) - posWithinFirstBlock, 0);
|
const uint64_t intoOffset = std::max<uint64_t>((blocksProcessed * idealBlockSize) - posWithinFirstBlock, 0);
|
||||||
const auto posWithinCurrentBlock = (blocksProcessed ? 0 : posWithinFirstBlock);
|
const uint32_t posWithinCurrentBlock = (blocksProcessed ? 0 : posWithinFirstBlock);
|
||||||
auto curAmt = idealBlockSize - posWithinCurrentBlock;
|
uint32_t curAmt = idealBlockSize - posWithinCurrentBlock;
|
||||||
const auto amountLeft = amount - *ret;
|
const auto amountLeft = amount - ret.value_or(0);
|
||||||
if(curAmt > amountLeft)
|
if(curAmt > amountLeft)
|
||||||
curAmt = amountLeft;
|
curAmt = static_cast<uint32_t>(amountLeft);
|
||||||
|
|
||||||
const bool useAlignedReadBuffer = (posWithinCurrentBlock != 0 || curAmt != idealBlockSize);
|
const bool useAlignedReadBuffer = (posWithinCurrentBlock != 0 || curAmt != idealBlockSize);
|
||||||
if(useAlignedReadBuffer && alignedReadBuffer.size() < idealBlockSize)
|
if(useAlignedReadBuffer && alignedReadBuffer.size() < idealBlockSize)
|
||||||
|
|
@ -34,7 +36,7 @@ optional<uint64_t> DiskReadDriver::readLogicalDisk(Communication& com, device_ev
|
||||||
|
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
auto readAmount = readLogicalDiskAligned(com, report, currentBlock * idealBlockSize,
|
auto readAmount = readLogicalDiskAligned(com, report, currentBlock * idealBlockSize,
|
||||||
useAlignedReadBuffer ? alignedReadBuffer.data() : into + intoOffset, idealBlockSize, timeout);
|
useAlignedReadBuffer ? alignedReadBuffer.data() : (into + intoOffset), idealBlockSize, timeout);
|
||||||
timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
|
timeout -= std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
|
||||||
|
|
||||||
if(!readAmount.has_value() || *readAmount == 0) {
|
if(!readAmount.has_value() || *readAmount == 0) {
|
||||||
|
|
@ -50,7 +52,7 @@ optional<uint64_t> DiskReadDriver::readLogicalDisk(Communication& com, device_ev
|
||||||
|
|
||||||
if(!ret)
|
if(!ret)
|
||||||
ret.emplace();
|
ret.emplace();
|
||||||
*ret += *readAmount;
|
*ret += std::min<uint64_t>(*readAmount, curAmt);
|
||||||
blocksProcessed++;
|
blocksProcessed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue