add overflow tests on pack offset variables
Change a few size and offset variables to more appropriate type, then add overflow tests on those offsets. This prevents any bad data to be generated/processed if off_t happens to not be large enough to handle some big packs. Better be safe than sorry. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
8723f21626
commit
d7dd02231f
@ -369,7 +369,7 @@ static int revalidate_loose_object(struct object_entry *entry,
|
||||
return check_loose_inflate(map, mapsize, size);
|
||||
}
|
||||
|
||||
static off_t write_object(struct sha1file *f,
|
||||
static unsigned long write_object(struct sha1file *f,
|
||||
struct object_entry *entry)
|
||||
{
|
||||
unsigned long size;
|
||||
@ -503,16 +503,23 @@ static off_t write_one(struct sha1file *f,
|
||||
struct object_entry *e,
|
||||
off_t offset)
|
||||
{
|
||||
unsigned long size;
|
||||
|
||||
/* offset is non zero if object is written already. */
|
||||
if (e->offset || e->preferred_base)
|
||||
/* offset starts from header size and cannot be zero
|
||||
* if it is written already.
|
||||
*/
|
||||
return offset;
|
||||
/* if we are deltified, write out its base object first. */
|
||||
|
||||
/* if we are deltified, write out base object first. */
|
||||
if (e->delta)
|
||||
offset = write_one(f, e->delta, offset);
|
||||
|
||||
e->offset = offset;
|
||||
return offset + write_object(f, e);
|
||||
size = write_object(f, e);
|
||||
|
||||
/* make sure off_t is sufficiently large not to wrap */
|
||||
if (offset > offset + size)
|
||||
die("pack too large for current definition of off_t");
|
||||
return offset + size;
|
||||
}
|
||||
|
||||
static void write_pack_file(void)
|
||||
|
@ -13,7 +13,8 @@ static const char unpack_usage[] = "git-unpack-objects [-n] [-q] [-r] < pack-fil
|
||||
|
||||
/* We always read in 4kB chunks. */
|
||||
static unsigned char buffer[4096];
|
||||
static unsigned long offset, len, consumed_bytes;
|
||||
static unsigned int offset, len;
|
||||
static off_t consumed_bytes;
|
||||
static SHA_CTX ctx;
|
||||
|
||||
/*
|
||||
@ -49,6 +50,10 @@ static void use(int bytes)
|
||||
die("used more bytes than were available");
|
||||
len -= bytes;
|
||||
offset += bytes;
|
||||
|
||||
/* make sure off_t is sufficiently large not to wrap */
|
||||
if (consumed_bytes > consumed_bytes + bytes)
|
||||
die("pack too large for current definition of off_t");
|
||||
consumed_bytes += bytes;
|
||||
}
|
||||
|
||||
@ -88,17 +93,17 @@ static void *get_data(unsigned long size)
|
||||
|
||||
struct delta_info {
|
||||
unsigned char base_sha1[20];
|
||||
unsigned long base_offset;
|
||||
unsigned nr;
|
||||
off_t base_offset;
|
||||
unsigned long size;
|
||||
void *delta;
|
||||
unsigned nr;
|
||||
struct delta_info *next;
|
||||
};
|
||||
|
||||
static struct delta_info *delta_list;
|
||||
|
||||
static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1,
|
||||
unsigned long base_offset,
|
||||
off_t base_offset,
|
||||
void *delta, unsigned long size)
|
||||
{
|
||||
struct delta_info *info = xmalloc(sizeof(*info));
|
||||
@ -113,7 +118,7 @@ static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1,
|
||||
}
|
||||
|
||||
struct obj_info {
|
||||
unsigned long offset;
|
||||
off_t offset;
|
||||
unsigned char sha1[20];
|
||||
};
|
||||
|
||||
@ -200,7 +205,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
|
||||
} else {
|
||||
unsigned base_found = 0;
|
||||
unsigned char *pack, c;
|
||||
unsigned long base_offset;
|
||||
off_t base_offset;
|
||||
unsigned lo, mid, hi;
|
||||
|
||||
pack = fill(1);
|
||||
|
14
index-pack.c
14
index-pack.c
@ -12,7 +12,7 @@ static const char index_pack_usage[] =
|
||||
|
||||
struct object_entry
|
||||
{
|
||||
unsigned long offset;
|
||||
off_t offset;
|
||||
unsigned long size;
|
||||
unsigned int hdr_size;
|
||||
enum object_type type;
|
||||
@ -22,7 +22,7 @@ struct object_entry
|
||||
|
||||
union delta_base {
|
||||
unsigned char sha1[20];
|
||||
unsigned long offset;
|
||||
off_t offset;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -83,7 +83,8 @@ static unsigned display_progress(unsigned n, unsigned total, unsigned last_pc)
|
||||
|
||||
/* We always read in 4kB chunks. */
|
||||
static unsigned char input_buffer[4096];
|
||||
static unsigned long input_offset, input_len, consumed_bytes;
|
||||
static unsigned int input_offset, input_len;
|
||||
static off_t consumed_bytes;
|
||||
static SHA_CTX input_ctx;
|
||||
static int input_fd, output_fd, pack_fd;
|
||||
|
||||
@ -129,6 +130,10 @@ static void use(int bytes)
|
||||
die("used more bytes than were available");
|
||||
input_len -= bytes;
|
||||
input_offset += bytes;
|
||||
|
||||
/* make sure off_t is sufficiently large not to wrap */
|
||||
if (consumed_bytes > consumed_bytes + bytes)
|
||||
die("pack too large for current definition of off_t");
|
||||
consumed_bytes += bytes;
|
||||
}
|
||||
|
||||
@ -216,7 +221,8 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size)
|
||||
static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_base)
|
||||
{
|
||||
unsigned char *p, c;
|
||||
unsigned long size, base_offset;
|
||||
unsigned long size;
|
||||
off_t base_offset;
|
||||
unsigned shift;
|
||||
|
||||
obj->offset = consumed_bytes;
|
||||
|
Loading…
Reference in New Issue
Block a user