Fix possible crash in DomainResolver.

App::CallDelayed() could be queued twice for a single key, if before
the delayed call we cleared entry in _attempts and created it again.
This commit is contained in:
John Preston 2019-03-20 13:23:14 +04:00
parent 8acd47bf2f
commit a59353df9f
2 changed files with 10 additions and 4 deletions

View File

@ -453,7 +453,7 @@ void DomainResolver::resolve(const AttemptKey &key) {
auto hosts = DnsDomains(); auto hosts = DnsDomains();
std::random_device rd; std::random_device rd;
ranges::shuffle(hosts, std::mt19937(rd())); ranges::shuffle(hosts, std::mt19937(rd()));
_attempts.emplace(key, std::move(hosts)); _attempts.emplace(key, Attempts{ std::move(hosts) });
sendNextRequest(key); sendNextRequest(key);
} }
@ -478,12 +478,13 @@ void DomainResolver::sendNextRequest(const AttemptKey &key) {
if (i == end(_attempts)) { if (i == end(_attempts)) {
return; return;
} }
auto &hosts = i->second; auto &attempts = i->second;
auto &hosts = attempts.hosts;
const auto host = hosts.back(); const auto host = hosts.back();
hosts.pop_back(); hosts.pop_back();
if (!hosts.empty()) { if (!hosts.empty()) {
App::CallDelayed(kSendNextTimeout, this, [=] { App::CallDelayed(kSendNextTimeout, &attempts.guard, [=] {
sendNextRequest(key); sendNextRequest(key);
}); });
} }

View File

@ -91,6 +91,11 @@ private:
QStringList ips; QStringList ips;
crl::time expireAt = 0; crl::time expireAt = 0;
};
struct Attempts {
std::vector<QString> hosts;
base::has_weak_ptr guard;
}; };
void resolve(const AttemptKey &key); void resolve(const AttemptKey &key);
@ -110,7 +115,7 @@ private:
crl::time expireAt)> _callback; crl::time expireAt)> _callback;
QNetworkAccessManager _manager; QNetworkAccessManager _manager;
std::map<AttemptKey, std::vector<QString>> _attempts; std::map<AttemptKey, Attempts> _attempts;
std::map<AttemptKey, std::vector<ServiceWebRequest>> _requests; std::map<AttemptKey, std::vector<ServiceWebRequest>> _requests;
std::map<AttemptKey, CacheEntry> _cache; std::map<AttemptKey, CacheEntry> _cache;
crl::time _lastTimestamp = 0; crl::time _lastTimestamp = 0;