Fix iterator invalidation bug

Standard says operator[] may invalidate iterators. Never actually
crashed though /shrug
This commit is contained in:
2024-03-03 20:44:13 -08:00
parent 8bf3aa7f56
commit ad11782029

View File

@@ -53,17 +53,21 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
if (keyUpdates < 100) { if (keyUpdates < 100) {
return; return;
} }
auto iter = map.find(removalKey);
for (; keyUpdates > 0 && removalIter != map.end(); --keyUpdates) { if (iter == map.end()) {
if (removalIter->second <= oldestVersion) { iter = map.begin();
removalIter = map.erase(removalIter); }
for (; keyUpdates > 0 && iter != map.end(); --keyUpdates) {
if (iter->second <= oldestVersion) {
iter = map.erase(iter);
} else { } else {
++removalIter; ++iter;
} }
} }
if (iter == map.end()) {
if (removalIter == map.end()) { removalKey.clear();
removalIter = map.begin(); } else {
removalKey = iter->first;
} }
} }
@@ -71,10 +75,7 @@ private:
int64_t keyUpdates = 0; int64_t keyUpdates = 0;
int64_t oldestVersion; int64_t oldestVersion;
std::unordered_map<std::string, int64_t, string_hash, std::equal_to<>> map; std::unordered_map<std::string, int64_t, string_hash, std::equal_to<>> map;
std::string removalKey;
// This iterator outliving the call to setOldestVersion is only safe because
// we only erase from within setOldestVersion
decltype(map.begin()) removalIter;
}; };
void ConflictSet::check(const ReadRange *reads, Result *results, void ConflictSet::check(const ReadRange *reads, Result *results,