odb: guard against data loss checking out a huge file

This introduces an additional guard for platforms where `unsigned long`
and `size_t` are not of the same size. If the size of an object in the
database would overflow `unsigned long`, instead we now exit with an
error.

A complete fix will have to update _many_ other functions throughout the
codebase to use `size_t` instead of `unsigned long`. It will have to be
implemented at some stage.

This commit puts in a stop-gap for the time being.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Matt Cooper <vtbassmatt@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Matt Cooper 2021-11-02 15:46:10 +00:00 committed by Junio C Hamano
parent e2ffeae3f6
commit d6a09e795d
3 changed files with 9 additions and 9 deletions

View File

@ -90,15 +90,15 @@ static inline unsigned long get_delta_hdr_size(const unsigned char **datap,
const unsigned char *top) const unsigned char *top)
{ {
const unsigned char *data = *datap; const unsigned char *data = *datap;
unsigned long cmd, size = 0; size_t cmd, size = 0;
int i = 0; int i = 0;
do { do {
cmd = *data++; cmd = *data++;
size |= (cmd & 0x7f) << i; size |= st_left_shift(cmd & 0x7f, i);
i += 7; i += 7;
} while (cmd & 0x80 && data < top); } while (cmd & 0x80 && data < top);
*datap = data; *datap = data;
return size; return cast_size_t_to_ulong(size);
} }
#endif #endif

View File

@ -1344,7 +1344,7 @@ static int parse_loose_header_extended(const char *hdr, struct object_info *oi,
unsigned int flags) unsigned int flags)
{ {
const char *type_buf = hdr; const char *type_buf = hdr;
unsigned long size; size_t size;
int type, type_len = 0; int type, type_len = 0;
/* /*
@ -1388,12 +1388,12 @@ static int parse_loose_header_extended(const char *hdr, struct object_info *oi,
if (c > 9) if (c > 9)
break; break;
hdr++; hdr++;
size = size * 10 + c; size = st_add(st_mult(size, 10), c);
} }
} }
if (oi->sizep) if (oi->sizep)
*oi->sizep = size; *oi->sizep = cast_size_t_to_ulong(size);
/* /*
* The length must be followed by a zero byte * The length must be followed by a zero byte

View File

@ -1059,7 +1059,7 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
unsigned long len, enum object_type *type, unsigned long *sizep) unsigned long len, enum object_type *type, unsigned long *sizep)
{ {
unsigned shift; unsigned shift;
unsigned long size, c; size_t size, c;
unsigned long used = 0; unsigned long used = 0;
c = buf[used++]; c = buf[used++];
@ -1073,10 +1073,10 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
break; break;
} }
c = buf[used++]; c = buf[used++];
size += (c & 0x7f) << shift; size = st_add(size, st_left_shift(c & 0x7f, shift));
shift += 7; shift += 7;
} }
*sizep = size; *sizep = cast_size_t_to_ulong(size);
return used; return used;
} }