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>
Matt Cooper committed
Nov 2, 2021 at 15:46 UTC
d6a09e795d77ddc76c5141047340dc3cb62355f4
3 files changed
+9
-9
delta.h
+3
-3
@@ -90,15 +90,15 @@ static inline unsigned long get_delta_hdr_size(const unsigned char **datap,
90
const unsigned char *top)
91
{
92
const unsigned char *data = *datap;
93
- unsigned long cmd, size = 0;
93
+ size_t cmd, size = 0;
94
int i = 0;
95
do {
96
cmd = *data++;
97
- size |= (cmd & 0x7f) << i;
97
+ size |= st_left_shift(cmd & 0x7f, i);
98
i += 7;
99
} while (cmd & 0x80 && data < top);
100
*datap = data;
101
- return size;
101
+ return cast_size_t_to_ulong(size);
102
}
103
104
#endif
object-file.c
+3
-3
@@ -1344,7 +1344,7 @@ static int parse_loose_header_extended(const char *hdr, struct object_info *oi,
1344
unsigned int flags)
1345
{
1346
const char *type_buf = hdr;
1347
- unsigned long size;
1347
+ size_t size;
1348
int type, type_len = 0;
1349
1350
/*
@@ -1388,12 +1388,12 @@ static int parse_loose_header_extended(const char *hdr, struct object_info *oi,
1388
if (c > 9)
1389
break;
1390
hdr++;
1391
- size = size * 10 + c;
1391
+ size = st_add(st_mult(size, 10), c);
1392
}
1393
}
1394
1395
if (oi->sizep)
1396
- *oi->sizep = size;
1396
+ *oi->sizep = cast_size_t_to_ulong(size);
1397
1398
/*
1399
* The length must be followed by a zero byte
packfile.c
+3
-3
@@ -1059,7 +1059,7 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
1059
unsigned long len, enum object_type *type, unsigned long *sizep)
1060
{
1061
unsigned shift;
1062
- unsigned long size, c;
1062
+ size_t size, c;
1063
unsigned long used = 0;
1064
1065
c = buf[used++];
@@ -1073,10 +1073,10 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
1073
break;
1074
}
1075
c = buf[used++];
1076
- size += (c & 0x7f) << shift;
1076
+ size = st_add(size, st_left_shift(c & 0x7f, shift));
1077
shift += 7;
1078
}
1079
- *sizep = size;
1079
+ *sizep = cast_size_t_to_ulong(size);
1080
return used;
1081
}
1082