From e3153dd5b0eb745cbdd40faaa81d1cca16a6bec6 Mon Sep 17 00:00:00 2001 From: Calle Wilund Date: Mon, 4 Sep 2023 12:59:34 +0000 Subject: [PATCH] Commitlog replayer: Range-check skip call Fixes #15269 If segment being replayed is corrupted/truncated we can attempt skipping completely bogues byte amounts, which can cause assert (i.e. crash) in file_data_source_impl. This is not a crash-level error, so ensure we range check the distance in the reader. v2: Add to corrupt_size if trying to skip more than available. The amount added is "wrong", but at least will ensure we log the fact that things are broken Closes scylladb/scylladb#15270 (cherry picked from commit 6ffb482bf3b86f4c6edad1f1eb0c922016693abe) --- db/commitlog/commitlog.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/db/commitlog/commitlog.cc b/db/commitlog/commitlog.cc index 0f5fdd5859..c9f0edfbc6 100644 --- a/db/commitlog/commitlog.cc +++ b/db/commitlog/commitlog.cc @@ -2628,12 +2628,20 @@ db::commitlog::read_log_file(sstring filename, sstring pfx, commit_load_reader_f return eof || next == pos; } future<> skip(size_t bytes) { - pos += bytes; - if (pos > file_size) { + auto n = std::min(file_size - pos, bytes); + pos += n; + if (pos == file_size) { eof = true; - pos = file_size; } - return fin.skip(bytes); + if (n < bytes) { + // if we are trying to skip past end, we have at least + // the bytes skipped or the source from where we read + // this corrupt. So add at least four bytes. This is + // inexact, but adding the full "bytes" is equally wrong + // since it could be complete garbled junk. + corrupt_size += std::max(n, sizeof(uint32_t)); + } + return fin.skip(n); } void stop() { eof = true;