diff --git a/git-compat-util.h b/git-compat-util.h index 5024814bd4..8809776407 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -614,12 +614,30 @@ static inline bool strip_suffix(const char *str, const char *suffix, int git_open_cloexec(const char *name, int flags); #define git_open(name) git_open_cloexec(name, O_RDONLY) -static inline size_t st_add(size_t a, size_t b) + +/* + * Help Clang; GCC generates the same instructions for both variants on + * x64 and aarch64. + */ +#ifdef __clang__ +#define st_add_overflow __builtin_add_overflow +#else +static inline bool st_add_overflow(size_t a, size_t b, size_t *out) { if (unsigned_add_overflows(a, b)) + return true; + *out = a + b; + return false; +} +#endif + +static inline size_t st_add(size_t a, size_t b) +{ + size_t result; + if (st_add_overflow(a, b, &result)) die("size_t overflow: %"PRIuMAX" + %"PRIuMAX, (uintmax_t)a, (uintmax_t)b); - return a + b; + return result; } #define st_add3(a,b,c) st_add(st_add((a),(b)),(c)) #define st_add4(a,b,c,d) st_add(st_add3((a),(b),(c)),(d)) diff --git a/strbuf.c b/strbuf.c index 3e04addc22..8610965d53 100644 --- a/strbuf.c +++ b/strbuf.c @@ -106,12 +106,10 @@ void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc) void strbuf_grow(struct strbuf *sb, size_t extra) { int new_buf = !sb->alloc; - if (unsigned_add_overflows(extra, 1) || - unsigned_add_overflows(sb->len, extra + 1)) - die("you want to use way too much memory"); + size_t new_len = st_add3(sb->len, extra, 1); if (new_buf) sb->buf = NULL; - ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); + ALLOC_GROW(sb->buf, new_len, sb->alloc); if (new_buf) sb->buf[0] = '\0'; }