summaryrefslogtreecommitdiff
path: root/src/indexer.c
diff options
context:
space:
mode:
authorlhchavez <lhchavez@lhchavez.com>2017-12-23 14:59:07 +0000
committerlhchavez <lhchavez@lhchavez.com>2017-12-23 14:59:07 +0000
commitc3514b0b82e90e660c996e81a525d42c025503ab (patch)
treec4fe81c1f539c23d7a95ac607a551cb11fec865d /src/indexer.c
parent9f7ad3c5d34d35a5ec2f34fa9cd8c92eff439329 (diff)
downloadlibgit2-c3514b0b82e90e660c996e81a525d42c025503ab.tar.gz
Fix unpack double free
If an element has been cached, but then the call to packfile_unpack_compressed() fails, the very next thing that happens is that its data is freed and then the element is not removed from the cache, which frees the data again. This change sets obj->data to NULL to avoid the double-free. It also stops trying to resolve deltas after two continuous failed rounds of resolution, and adds a test for this.
Diffstat (limited to 'src/indexer.c')
-rw-r--r--src/indexer.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/src/indexer.c b/src/indexer.c
index 7eec0d612..a5e842272 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -844,6 +844,7 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats)
static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats)
{
unsigned int i;
+ int error;
struct delta_info *delta;
int progressed = 0, non_null = 0, progress_cb_result;
@@ -858,8 +859,13 @@ static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats)
non_null = 1;
idx->off = delta->delta_off;
- if (git_packfile_unpack(&obj, idx->pack, &idx->off) < 0)
- continue;
+ if ((error = git_packfile_unpack(&obj, idx->pack, &idx->off)) < 0) {
+ if (error == GIT_PASSTHROUGH) {
+ /* We have not seen the base object, we'll try again later. */
+ continue;
+ }
+ return -1;
+ }
if (hash_and_save(idx, &obj, delta->delta_off) < 0)
continue;