summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-02-20 08:40:40 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2015-02-20 08:40:40 +0100
commit5091aff7823dd7badd821afc89b1c4c6761b13cf (patch)
treeb7afd56f87a8cfc2040ee13cba73932f7755d391
parentd15884ce840c7eeac54fc408fdc33e03cd01bc32 (diff)
parent8588cb0cbfadcd66061062bd0ab170a1419e006f (diff)
downloadlibgit2-5091aff7823dd7badd821afc89b1c4c6761b13cf.tar.gz
Merge pull request #2907 from jasonhaslam/git_packfile_unpack_race
Fix race in git_packfile_unpack.
-rw-r--r--src/pack.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/src/pack.c b/src/pack.c
index 26a6036c2..3c646b778 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -56,6 +56,7 @@ static git_pack_cache_entry *new_cache_object(git_rawobj *source)
if (!e)
return NULL;
+ git_atomic_inc(&e->refcount);
memcpy(&e->raw, source, sizeof(git_rawobj));
return e;
@@ -145,7 +146,11 @@ static void free_lowest_entry(git_pack_cache *cache)
}
}
-static int cache_add(git_pack_cache *cache, git_rawobj *base, git_off_t offset)
+static int cache_add(
+ git_pack_cache_entry **cached_out,
+ git_pack_cache *cache,
+ git_rawobj *base,
+ git_off_t offset)
{
git_pack_cache_entry *entry;
int error, exists = 0;
@@ -171,6 +176,8 @@ static int cache_add(git_pack_cache *cache, git_rawobj *base, git_off_t offset)
assert(error != 0);
kh_value(cache->entries, k) = entry;
cache->memory_used += entry->raw.len;
+
+ *cached_out = entry;
}
git_mutex_unlock(&cache->lock);
/* Somebody beat us to adding it into the cache */
@@ -702,7 +709,7 @@ int git_packfile_unpack(
* long as it's not already the cached one.
*/
if (!cached)
- free_base = !!cache_add(&p->bases, obj, elem->base_key);
+ free_base = !!cache_add(&cached, &p->bases, obj, elem->base_key);
elem = &stack[elem_pos - 1];
curpos = elem->offset;