Fuzzer thinks FdbVersionedMap seems ok

This commit is contained in:
2024-05-28 16:35:58 -07:00
parent 3aa192255e
commit dc587e627b

View File

@@ -1135,6 +1135,9 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
VersionedData versionedData; VersionedData versionedData;
std::map<Version, StandaloneVerUpdateRef> std::map<Version, StandaloneVerUpdateRef>
mutationLog; // versions (durableVersion, version] mutationLog; // versions (durableVersion, version]
std::map<Version, std::vector<Arena>>
freeable; // for each version, arena's that must be held until that
// version is < oldestVersion
StandaloneVerUpdateRef &addVersionToMutationLog(Version v) { StandaloneVerUpdateRef &addVersionToMutationLog(Version v) {
// return existing version... // return existing version...
@@ -1148,6 +1151,24 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
return u; return u;
} }
void expandClear(Key &begin, Key &end, VersionedData const &data,
Arena &arena) {
// Expand the clear
const auto &d = data.atLatest();
// If another clear overlaps the beginning of this one, engulf it
auto i = d.lastLess(begin);
if (i && i->isClearTo() && i->getEndKey() >= begin)
begin = copy(arena, i.key());
// If another clear overlaps the end of this one, engulf it; otherwise
// expand
i = d.lastLessOrEqual(end);
if (i && i->isClearTo() && i->getEndKey() >= end) {
end = copy(arena, i->getEndKey());
}
}
void addMutations(const Mutation *mutations, int numMutations, void addMutations(const Mutation *mutations, int numMutations,
int64_t version) { int64_t version) {
versionedData.createNewVersion(version); versionedData.createNewVersion(version);
@@ -1164,8 +1185,6 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
? copy(arena, Key{m.param2, m.param2Len}) ? copy(arena, Key{m.param2, m.param2Len})
: keyAfter(param1, arena); : keyAfter(param1, arena);
verUpdateRef.mutations.push_back(
Mutation{param1.p, param2.p, param1.len, param2.len, m.type});
if (m.type == weaselab::VersionedMap::Set) { if (m.type == weaselab::VersionedMap::Set) {
// VersionedMap (data) is bookkeeping all empty ranges. If the key to be // VersionedMap (data) is bookkeeping all empty ranges. If the key to be
// set is new, it is supposed to be in a range what was empty. Break the // set is new, it is supposed to be in a range what was empty. Break the
@@ -1201,16 +1220,21 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
if (param2.len == 0) { if (param2.len == 0) {
param2 = keyAfter(param1, arena); param2 = keyAfter(param1, arena);
} }
expandClear(param1, param2, versionedData, arena);
versionedData.erase(param1, param2); versionedData.erase(param1, param2);
assert(param2 > param1); assert(param2 > param1);
assert( assert(
!versionedData.isClearContaining(versionedData.atLatest(), param1)); !versionedData.isClearContaining(versionedData.atLatest(), param1));
versionedData.insert(param1, ValueOrClearToRef::clearTo(param2)); versionedData.insert(param1, ValueOrClearToRef::clearTo(param2));
} }
verUpdateRef.mutations.push_back(
Mutation{param1.p, param2.p, param1.len, param2.len, m.type});
} }
} }
void setOldestVersion(int64_t oldestVersion) { void setOldestVersion(int64_t oldestVersion) {
auto &freeVec = freeable[versionedData.getLatestVersion()];
auto iter = mutationLog.begin(); auto iter = mutationLog.begin();
while (iter != mutationLog.end() && iter->first <= oldestVersion) { while (iter != mutationLog.end() && iter->first <= oldestVersion) {
for (const auto &m : iter->second.mutations) { for (const auto &m : iter->second.mutations) {
@@ -1231,10 +1255,11 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
} }
} }
} }
// TODO this is a heap-use-after-free freeVec.push_back(std::move(iter->second.arena));
iter = mutationLog.erase(iter); iter = mutationLog.erase(iter);
} }
versionedData.forgetVersionsBefore(oldestVersion); versionedData.forgetVersionsBefore(oldestVersion);
freeable.erase(freeable.begin(), freeable.lower_bound(oldestVersion));
} }
}; };
@@ -1319,8 +1344,6 @@ VersionedMap::Iterator::operator*() const {
} }
result.version = impl->iter.insertVersion(); result.version = impl->iter.insertVersion();
assert(result.param1[0] != 0);
assert(result.param2[0] != 0);
return result; return result;
} }