sha1_file: don't convert off_t to size_t too early to avoid potential die()
authorSteffen Prohaska <prohaska@zib.de>
Sun, 21 Sep 2014 10:03:26 +0000 (12:03 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 22 Sep 2014 19:40:55 +0000 (12:40 -0700)
xsize_t() checks if an off_t argument can be safely converted to
a size_t return value. If the check is executed too early, it could
fail for large files on 32-bit architectures even if the size_t code
path is not taken. Other paths might be able to handle the large file.
Specifically, index_stream_convert_blob() is able to handle a large file
if a filter is configured that returns a small result.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
sha1_file.c
index 423ec64e8732687afbd5c118885a6864927e2db6..7b2612f733e8152777e86952c41f03553129d1e2 100644 (file)
@@ -3178,17 +3178,22 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st,
             enum object_type type, const char *path, unsigned flags)
 {
        int ret;
-       size_t size = xsize_t(st->st_size);
 
+       /*
+        * Call xsize_t() only when needed to avoid potentially unnecessary
+        * die() for large files.
+        */
        if (type == OBJ_BLOB && path && would_convert_to_git_filter_fd(path))
                ret = index_stream_convert_blob(sha1, fd, path, flags);
        else if (!S_ISREG(st->st_mode))
                ret = index_pipe(sha1, fd, type, path, flags);
-       else if (size <= big_file_threshold || type != OBJ_BLOB ||
+       else if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||
                 (path && would_convert_to_git(path)))
-               ret = index_core(sha1, fd, size, type, path, flags);
+               ret = index_core(sha1, fd, xsize_t(st->st_size), type, path,
+                                flags);
        else
-               ret = index_stream(sha1, fd, size, type, path, flags);
+               ret = index_stream(sha1, fd, xsize_t(st->st_size), type, path,
+                                  flags);
        close(fd);
        return ret;
 }