Fix double free in Store::queryPathInfo()

It was holding on to a Value* (i.e. a std::shared_ptr<ValidPathInfo>*)
outside of the pathInfoCache lock, so the std::shared_ptr could be
destroyed between the release of the lock and the decrement of the
std::shared_ptr refcount. This can happen if more than
'path-info-cache-size' paths are added in the meantime, *or* if
clearPathInfoCache() is called. The hydra-queue-runner queue monitor
thread periodically calls the later, so is likely to trigger a crash.

Fixes https://github.com/NixOS/hydra/issues/542.
This commit is contained in:
Eelco Dolstra 2018-03-09 14:19:51 +01:00
parent dc83c8eea5
commit 24b739817f
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE

View file

@ -2,6 +2,7 @@
#include <map> #include <map>
#include <list> #include <list>
#include <experimental/optional>
namespace nix { namespace nix {
@ -63,18 +64,17 @@ public:
/* Look up an item in the cache. If it exists, it becomes the most /* Look up an item in the cache. If it exists, it becomes the most
recently used item. */ recently used item. */
// FIXME: use boost::optional? std::experimental::optional<Value> get(const Key & key)
Value * get(const Key & key)
{ {
auto i = data.find(key); auto i = data.find(key);
if (i == data.end()) return 0; if (i == data.end()) return {};
/* Move this item to the back of the LRU list. */ /* Move this item to the back of the LRU list. */
lru.erase(i->second.first.it); lru.erase(i->second.first.it);
auto j = lru.insert(lru.end(), i); auto j = lru.insert(lru.end(), i);
i->second.first.it = j; i->second.first.it = j;
return &i->second.second; return i->second.second;
} }
size_t size() size_t size()