mirror of
https://github.com/google/leveldb.git
synced 2025-02-04 07:10:10 +08:00
Report corruption for invalid InternalKeys read from disk. Fixes #966.
This commit is contained in:
parent
4fb146810c
commit
d328a35b5c
@ -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,
|
||||
|
@ -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_; }
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -17,6 +17,10 @@ namespace leveldb {
|
||||
|
||||
Comparator::~Comparator() = default;
|
||||
|
||||
bool Comparator::IsInternal() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class BytewiseComparatorImpl : public Comparator {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user