Jeff King wrote: > AFAIK there's no way to turn it on for specific functions, but I'm far > from a gcc-warning guru. Even if you could, though, the error may be far > from the function (e.g., if we store the result in an ssize_t and then > compare that with a size_t). It turns out that yes, we have two of those. Both handle errors separately already, so they should be safe. While investigating the second, I noticed that read_in_full can overflow its return value. malloc doesn't typically allow allocating a buffer with size greater than SSIZE_MAX so this should be safe, but it would be confusing to static analyzers. Combining these observations yields the following (just for illustration): diff --git i/bulk-checkin.c w/bulk-checkin.c index 9a1f6c49ab..f8e3060041 100644 --- i/bulk-checkin.c +++ w/bulk-checkin.c @@ -114,7 +114,7 @@ static int stream_to_pack(struct bulk_checkin_state *state, unsigned char ibuf[16384]; if (size && !s.avail_in) { - ssize_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf); + size_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf); if (read_in_full(fd, ibuf, rsize) != rsize) die("failed to read %d bytes from '%s'", (int)rsize, path); diff --git i/combine-diff.c w/combine-diff.c index 9e163d5ada..e966d4f393 100644 --- i/combine-diff.c +++ w/combine-diff.c @@ -1026,7 +1026,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, result_size = fill_textconv(textconv, df, &result); free_filespec(df); } else if (0 <= (fd = open(elem->path, O_RDONLY))) { - size_t len = xsize_t(st.st_size); + ssize_t len = xssize_t(st.st_size); ssize_t done; int is_file, i; @@ -1040,6 +1040,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, if (!is_file) elem->mode = canon_mode(S_IFLNK); + if (len > ULONG_MAX) + die("cannot handle files this big"); result_size = len; result = xmallocz(len); diff --git i/git-compat-util.h w/git-compat-util.h index 6678b488cc..20fea81589 100644 --- i/git-compat-util.h +++ w/git-compat-util.h @@ -903,6 +903,13 @@ static inline size_t xsize_t(off_t len) return (size_t)len; } +static inline ssize_t xssize_t(off_t len) +{ + if (len > SSIZE_MAX) + die("cannot handle files this big"); + return (ssize_t)len; +} + __attribute__((format (printf, 3, 4))) extern int xsnprintf(char *dst, size_t max, const char *fmt, ...); diff --git i/wrapper.c w/wrapper.c index 36630e5d18..2b52b7367d 100644 --- i/wrapper.c +++ w/wrapper.c @@ -314,6 +314,9 @@ ssize_t read_in_full(int fd, void *buf, size_t count) char *p = buf; ssize_t total = 0; + if (count > SSIZE_MAX) + BUG("read_in_full called with absurdly high count %"PRIuMAX, + (uintmax_t) count); while (count > 0) { ssize_t loaded = xread(fd, p, count); if (loaded < 0)