Skip to content

Commit

Permalink
Fix dead loop with kSkipAnyCorruptedRecords mode selected in some cas…
Browse files Browse the repository at this point in the history
…es (#11955) (#11979)

Summary:
With fragmented record span across multiple blocks, if any following blocks corrupted with arbitary data, and intepreted log number less than the current log number, program will fall into infinite loop due to
not skipping buffer leading bytes

Pull Request resolved: #11979

Test Plan: existing unit tests

Reviewed By: ajkr

Differential Revision: D50604408

Pulled By: jowlyzhang

fbshipit-source-id: e50a0c7e7c3d293fb9d5afec0a3eb4a1835b7a3b
  • Loading branch information
qiuchengxuan authored and facebook-github-bot committed Oct 25, 2023
1 parent dc87847 commit f2c9075
Showing 1 changed file with 14 additions and 7 deletions.
21 changes: 14 additions & 7 deletions db/log_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -469,12 +469,14 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result, size_t* drop_size,
const unsigned int type = header[6];
const uint32_t length = a | (b << 8);
int header_size = kHeaderSize;
if ((type >= kRecyclableFullType && type <= kRecyclableLastType) ||
type == kRecyclableUserDefinedTimestampSizeType) {
const bool is_recyclable_type =
((type >= kRecyclableFullType && type <= kRecyclableLastType) ||
type == kRecyclableUserDefinedTimestampSizeType);
if (is_recyclable_type) {
header_size = kRecyclableHeaderSize;
if (end_of_buffer_offset_ - buffer_.size() == 0) {
recycled_ = true;
}
header_size = kRecyclableHeaderSize;
// We need enough for the larger header
if (buffer_.size() < static_cast<size_t>(kRecyclableHeaderSize)) {
int r = kEof;
Expand All @@ -483,11 +485,8 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result, size_t* drop_size,
}
continue;
}
const uint32_t log_num = DecodeFixed32(header + 7);
if (log_num != log_number_) {
return kOldRecord;
}
}

if (header_size + length > buffer_.size()) {
assert(buffer_.size() >= static_cast<size_t>(header_size));
*drop_size = buffer_.size();
Expand All @@ -499,6 +498,14 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result, size_t* drop_size,
return kBadRecordLen;
}

if (is_recyclable_type) {
const uint32_t log_num = DecodeFixed32(header + 7);
if (log_num != log_number_) {
buffer_.remove_prefix(header_size + length);
return kOldRecord;
}
}

if (type == kZeroType && length == 0) {
// Skip zero length record without reporting any drops since
// such records are produced by the mmap based writing code in
Expand Down

0 comments on commit f2c9075

Please sign in to comment.