]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb: guard against data loss checking out a huge file
authorMatt Cooper <vtbassmatt@gmail.com>
Tue, 2 Nov 2021 15:46:10 +0000 (15:46 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Nov 2021 18:22:27 +0000 (11:22 -0700)
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>
delta.h
object-file.c
packfile.c

diff --git a/delta.h b/delta.h
index 2df5fe13d954dfad4c6b1e80be7b45b281d7ef6d..8a56ec07992c75b021fca970d37e22f5e8a8bb48 100644 (file)
--- a/delta.h
+++ b/delta.h
@@ -90,15 +90,15 @@ static inline unsigned long get_delta_hdr_size(const unsigned char **datap,
                                               const unsigned char *top)
 {
        const unsigned char *data = *datap;
-       unsigned long cmd, size = 0;
+       size_t cmd, size = 0;
        int i = 0;
        do {
                cmd = *data++;
-               size |= (cmd & 0x7f) << i;
+               size |= st_left_shift(cmd & 0x7f, i);
                i += 7;
        } while (cmd & 0x80 && data < top);
        *datap = data;
-       return size;
+       return cast_size_t_to_ulong(size);
 }
 
 #endif
index f233b440b22c061cbdac1db019b1e8b58c093324..70e456fc2a3c96a15d384da35f9aa7ea5666de47 100644 (file)
@@ -1344,7 +1344,7 @@ static int parse_loose_header_extended(const char *hdr, struct object_info *oi,
                                       unsigned int flags)
 {
        const char *type_buf = hdr;
-       unsigned long size;
+       size_t size;
        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)
                                break;
                        hdr++;
-                       size = size * 10 + c;
+                       size = st_add(st_mult(size, 10), c);
                }
        }
 
        if (oi->sizep)
-               *oi->sizep = size;
+               *oi->sizep = cast_size_t_to_ulong(size);
 
        /*
         * The length must be followed by a zero byte
index 755aa7aec5efbfe4191a7aba32cfe0a4afab4956..3ccea004396ca21a141e7792c55087f96a9c14b1 100644 (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 shift;
-       unsigned long size, c;
+       size_t size, c;
        unsigned long used = 0;
 
        c = buf[used++];
@@ -1073,10 +1073,10 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
                        break;
                }
                c = buf[used++];
-               size += (c & 0x7f) << shift;
+               size = st_add(size, st_left_shift(c & 0x7f, shift));
                shift += 7;
        }
-       *sizep = size;
+       *sizep = cast_size_t_to_ulong(size);
        return used;
 }