Report corruption for invalid InternalKeys read from disk. Fixes #966.

This commit is contained in:
Christopher Jeffrey 2022-03-27 02:40:45 -04:00
parent 4fb146810c
commit d328a35b5c
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
6 changed files with 22 additions and 2 deletions

View File

@ -96,6 +96,10 @@ void InternalKeyComparator::FindShortSuccessor(std::string* key) const {
}
}
bool InternalKeyComparator::IsInternal() const {
return true;
}
const char* InternalFilterPolicy::Name() const { return user_policy_->Name(); }
void InternalFilterPolicy::CreateFilter(const Slice* keys, int n,

View File

@ -110,6 +110,7 @@ class InternalKeyComparator : public Comparator {
void FindShortestSeparator(std::string* start,
const Slice& limit) const override;
void FindShortSuccessor(std::string* key) const override;
bool IsInternal() const override;
const Comparator* user_comparator() const { return user_comparator_; }

View File

@ -87,6 +87,7 @@ void VersionEdit::EncodeTo(std::string* dst) const {
static bool GetInternalKey(Slice* input, InternalKey* dst) {
Slice str;
if (GetLengthPrefixedSlice(input, &str)) {
if (str.size() < 8) return false;
return dst->DecodeFrom(str);
} else {
return false;

View File

@ -52,6 +52,9 @@ class LEVELDB_EXPORT Comparator {
// Simple comparator implementations may return with *key unchanged,
// i.e., an implementation of this method that does nothing is correct.
virtual void FindShortSuccessor(std::string* key) const = 0;
// For internal usage only.
virtual bool IsInternal() const;
};
// Return a builtin comparator that uses lexicographic byte-wise

View File

@ -162,6 +162,11 @@ class Block::Iter : public Iterator {
}
void Seek(const Slice& target) override {
if (comparator_->IsInternal() && target.size() < 8) {
CorruptionError();
return;
}
// Binary search in restart array to find the last restart point
// with a key < target
uint32_t left = 0;
@ -191,7 +196,8 @@ class Block::Iter : public Iterator {
const char* key_ptr =
DecodeEntry(data_ + region_offset, data_ + restarts_, &shared,
&non_shared, &value_length);
if (key_ptr == nullptr || (shared != 0)) {
if (key_ptr == nullptr || (shared != 0) ||
(comparator_->IsInternal() && non_shared < 8)) {
CorruptionError();
return;
}
@ -261,7 +267,8 @@ class Block::Iter : public Iterator {
// Decode next entry
uint32_t shared, non_shared, value_length;
p = DecodeEntry(p, limit, &shared, &non_shared, &value_length);
if (p == nullptr || key_.size() < shared) {
if (p == nullptr || key_.size() < shared ||
(comparator_->IsInternal() && shared + non_shared < 8)) {
CorruptionError();
return false;
} else {

View File

@ -17,6 +17,10 @@ namespace leveldb {
Comparator::~Comparator() = default;
bool Comparator::IsInternal() const {
return false;
}
namespace {
class BytewiseComparatorImpl : public Comparator {
public: