Skip to content

Commit

Permalink
index-pack: fix truncation of off_t in comparison
Browse files Browse the repository at this point in the history
Commit c6458e6 (index-pack: kill union delta_base to save
memory, 2015-04-18) refactored the comparison functions used
in sorting and binary searching our delta list. The
resulting code does something like:

  int cmp_offsets(off_t a, off_t b)
  {
	  return a - b;
  }

This works most of the time, but produces nonsensical
results when the difference between the two offsets is
larger than what can be stored in an "int". This can lead to
unresolved deltas if the packsize is larger than 2G (even on
64-bit systems, an int is still typically 32 bits):

  $ git clone git://github.com/mozilla/gecko-dev
  Cloning into 'gecko-dev'...
  remote: Counting objects: 4800161, done.
  remote: Compressing objects: 100% (178/178), done.
  remote: Total 4800161 (delta 88), reused 0 (delta 0), pack-reused 4799978
  Receiving objects: 100% (4800161/4800161), 2.21 GiB | 3.26 MiB/s, done.
  Resolving deltas:  99% (3808820/3811944), completed with 0 local objects.
  fatal: pack has 3124 unresolved deltas
  fatal: index-pack failed

We can fix it by doing direct comparisons between the
offsets and returning constants; the callers only care about
the sign of the comparison, not the magnitude.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Jun 4, 2015
1 parent c6458e6 commit f0e7f11
Showing 1 changed file with 6 additions and 2 deletions.
8 changes: 6 additions & 2 deletions builtin/index-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,9 @@ static int compare_ofs_delta_bases(off_t offset1, off_t offset2,
int cmp = type1 - type2;
if (cmp)
return cmp;
return offset1 - offset2;
return offset1 < offset2 ? -1 :
offset1 > offset2 ? 1 :
0;
}

static int find_ofs_delta(const off_t offset, enum object_type type)
Expand Down Expand Up @@ -1051,7 +1053,9 @@ static int compare_ofs_delta_entry(const void *a, const void *b)
const struct ofs_delta_entry *delta_a = a;
const struct ofs_delta_entry *delta_b = b;

return delta_a->offset - delta_b->offset;
return delta_a->offset < delta_b->offset ? -1 :
delta_a->offset > delta_b->offset ? 1 :
0;
}

static int compare_ref_delta_entry(const void *a, const void *b)
Expand Down

0 comments on commit f0e7f11

Please sign in to comment.