pack-objects: do not truncate result in-pack object size on 32-bit systems
A typical diff will not show what's going on and you need to see full
functions. The core code is like this, at the end of of write_one()
e->idx.offset = *offset;
size = write_object(f, e, *offset);
if (!size) {
e->idx.offset = recursing;
return WRITE_ONE_BREAK;
}
written_list[nr_written++] = &e->idx;
/* make sure off_t is sufficiently large not to wrap */
if (signed_add_overflows(*offset, size))
die("pack too large for current definition of off_t");
*offset += size;
Here we can see that the in-pack object size is returned by
write_object (or indirectly by write_reuse_object). And it's used to
calculate object offsets, which end up in the pack index file,
generated at the end.
If "size" overflows (on 32-bit sytems, unsigned long is 32-bit while
off_t can be 64-bit), we got wrong offsets and produce incorrect .idx
file, which may make it look like the .pack file is corrupted.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
da49a7da3a
commit
af92a645d3
@ -341,7 +341,7 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return 0 if we will bust the pack-size limit */
|
/* Return 0 if we will bust the pack-size limit */
|
||||||
static unsigned long write_reuse_object(struct sha1file *f, struct object_entry *entry,
|
static off_t write_reuse_object(struct sha1file *f, struct object_entry *entry,
|
||||||
unsigned long limit, int usable_delta)
|
unsigned long limit, int usable_delta)
|
||||||
{
|
{
|
||||||
struct packed_git *p = entry->in_pack;
|
struct packed_git *p = entry->in_pack;
|
||||||
@ -415,11 +415,12 @@ static unsigned long write_reuse_object(struct sha1file *f, struct object_entry
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return 0 if we will bust the pack-size limit */
|
/* Return 0 if we will bust the pack-size limit */
|
||||||
static unsigned long write_object(struct sha1file *f,
|
static off_t write_object(struct sha1file *f,
|
||||||
struct object_entry *entry,
|
struct object_entry *entry,
|
||||||
off_t write_offset)
|
off_t write_offset)
|
||||||
{
|
{
|
||||||
unsigned long limit, len;
|
unsigned long limit;
|
||||||
|
off_t len;
|
||||||
int usable_delta, to_reuse;
|
int usable_delta, to_reuse;
|
||||||
|
|
||||||
if (!pack_to_stdout)
|
if (!pack_to_stdout)
|
||||||
@ -491,7 +492,7 @@ static enum write_one_status write_one(struct sha1file *f,
|
|||||||
struct object_entry *e,
|
struct object_entry *e,
|
||||||
off_t *offset)
|
off_t *offset)
|
||||||
{
|
{
|
||||||
unsigned long size;
|
off_t size;
|
||||||
int recursing;
|
int recursing;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user