ref: 09cdf057aa0db2d8d63eedc7718f3dea0c6075ac
parent: 230bca37cdbc79da43536fe58808db19457a3ed5
parent: 6316f60fcda342ca8bbff85dc8702c0d4db65d88
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Dec 27 20:11:49 EST 2020
packfiles: fix indexing large pack files (thanks Igor Boehm) This fixes two bugs with packfiles larger than 2 gigs in size. When writing out the index, we were incremeneting the index of the 64 bit offset multiple times due to macro expansion; this patch changes it so that we only increment it once per iteration. When reading the index, we were interpreting the large offset index as the offset of the 64 bit offset, leading to a garbled index. This diff also fixes our interpretation of the packfile, so we read all objects correctly, even when they're at a large offset.
--- a/pack.c
+++ b/pack.c
@@ -673,11 +673,21 @@
goto err;
i = GETBE32(idx + oo);
o = i & 0xffffffffULL;
+ /*
+ * Large offsets (i.e. 64-bit) are encoded as an index
+ * into the next table with the MSB bit set.
+ */
if(o & (1ull << 31)){
- o &= 0x7fffffff;
- if(o < 0 || o + 8 >= nidx)
+ o &= 0x7fffffffULL;
+ oo = 8; /* Header */
+ oo += 256*4; /* Fanout table */
+ oo += Hashsz*nent; /* Hashes */
+ oo += 4*nent; /* Checksums */
+ oo += 4*nent; /* 32-bit Offsets */
+ oo += 8*o; /* 64-bit Offset offset */
+ if(oo < 0 || oo + 8 >= nidx)
goto err;
- o = GETBE64(idx + o);
+ o = GETBE64(idx + oo);
}
return o;
@@ -1146,14 +1156,16 @@
nbig = 0;
for(i = 0; i < nobj; i++){
- if(obj[i]->off <= (1ull<<31))
+ if(obj[i]->off < (1ull<<31))
PUTBE32(buf, obj[i]->off);
- else
- PUTBE32(buf, (1ull << 31) | nbig++);
+ else{
+ PUTBE32(buf, (1ull << 31) | nbig);
+ nbig++;
+ }
hwrite(f, buf, 4, &st);
}
for(i = 0; i < nobj; i++){
- if(obj[i]->off > (1ull<<31)){
+ if(obj[i]->off >= (1ull<<31)){
PUTBE64(buf, obj[i]->off);
hwrite(f, buf, 8, &st);
}
--- a/save.c
+++ b/save.c
@@ -254,6 +254,8 @@
e = dirent(&ent, &nent, elt);
if(e->islink)
sysfatal("symlinks may not be modified: %s", *path);
+ if(e->ismod)
+ sysfatal("submodules may not be modified: %s", *path);
if(isdir){
e->mode = DMDIR | 0755;
sub[nsub] = readobject(e->h);