From 494acf7a54c114c231e73afdbe514befa60ecc03 Mon Sep 17 00:00:00 2001 From: Steve Atherton Date: Sat, 31 Jul 2021 11:33:53 -0700 Subject: [PATCH] Bug fixes with block memory lifetime and handling reads that cross the end of file barrier. --- fdbrpc/AsyncFileEncrypted.actor.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/fdbrpc/AsyncFileEncrypted.actor.cpp b/fdbrpc/AsyncFileEncrypted.actor.cpp index 1df9345998..a354a8074e 100644 --- a/fdbrpc/AsyncFileEncrypted.actor.cpp +++ b/fdbrpc/AsyncFileEncrypted.actor.cpp @@ -53,7 +53,7 @@ public: return Standalone(decrypted, arena); } - ACTOR static Future read(AsyncFileEncrypted* self, void* data, int length, int offset) { + ACTOR static Future read(AsyncFileEncrypted* self, void* data, int length, int64_t offset) { state const uint16_t firstBlock = offset / FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE; state const uint16_t lastBlock = (offset + length - 1) / FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE; state uint16_t block; @@ -61,15 +61,14 @@ public: state int bytesRead = 0; ASSERT(self->mode == AsyncFileEncrypted::Mode::READ_ONLY); for (block = firstBlock; block <= lastBlock; ++block) { - state StringRef plaintext; + state Standalone plaintext; auto cachedBlock = self->readBuffers.get(block); if (cachedBlock.present()) { plaintext = cachedBlock.get(); } else { - Standalone _plaintext = wait(readBlock(self, block)); - self->readBuffers.insert(block, _plaintext); - plaintext = _plaintext; + wait(store(plaintext, readBlock(self, block))); + self->readBuffers.insert(block, plaintext); } auto start = (block == firstBlock) ? plaintext.begin() + (offset % FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE) : plaintext.begin(); @@ -79,6 +78,14 @@ public: if ((offset + length) % FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE == 0) { end = plaintext.end(); } + + // The block could be short if it includes or is after the end of the file. + end = std::min(end, plaintext.end()); + // If the start position is at or after the end of the block, the read is complete. + if (start == end || start >= plaintext.end()) { + break; + } + std::copy(start, end, output); output += (end - start); bytesRead += (end - start);