diff options
author | Patrick Steinhardt <ps@pks.im> | 2020-02-07 12:50:39 +0100 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2020-02-07 13:08:23 +0100 |
commit | 7d1b17744a958890cae4648d4b38de2999832d77 (patch) | |
tree | 1cbf181d661f0842b0bf1d425c52d7b596c59c4a | |
parent | 775af0159bbb449dc2c800ffb1644250932fe6c1 (diff) | |
download | libgit2-7d1b17744a958890cae4648d4b38de2999832d77.tar.gz |
cache: fix invalid memory access in case updating cache entry fails
When adding a new entry to our cache where an entry with the same OID
exists already, then we only update the existing entry in case it is
unparsed and the new entry is parsed. Currently, we do not check the
return value of `git_oidmap_set` though when updating the existing
entry. As a result, we will _not_ have updated the existing entry if
`git_oidmap_set` fails, but have decremented its refcount and
incremented the new entry's refcount. Later on, this may likely lead to
dereferencing invalid memory.
Fix the issue by checking the return value of `git_oidmap_set`. In case
it fails, we will simply keep the existing stored instead, even though
it's unparsed.
-rw-r--r-- | src/cache.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/cache.c b/src/cache.c index 32ba993b0..af42b3959 100644 --- a/src/cache.c +++ b/src/cache.c @@ -208,10 +208,14 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) entry = stored_entry; } else if (stored_entry->flags == GIT_CACHE_STORE_RAW && entry->flags == GIT_CACHE_STORE_PARSED) { - git_cached_obj_decref(stored_entry); - git_cached_obj_incref(entry); - - git_oidmap_set(cache->map, &entry->oid, entry); + if (git_oidmap_set(cache->map, &entry->oid, entry) == 0) { + git_cached_obj_decref(stored_entry); + git_cached_obj_incref(entry); + } else { + git_cached_obj_decref(entry); + git_cached_obj_incref(stored_entry); + entry = stored_entry; + } } else { /* NO OP */ } |