diff options
author | Jonathan Nieder <jrnieder@gmail.com> | 2010-10-10 21:59:26 -0500 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2011-02-10 13:47:56 -0800 |
commit | 1368f65002bf39fdde7dd736a75ae35475184371 (patch) | |
tree | cb0d57165c5b1f710bb5e6499fa322185a8deb2f | |
parent | a8e4a5943a63c8fd4a3a9b70ccf4608bcc973707 (diff) | |
download | git-1368f65002bf39fdde7dd736a75ae35475184371.tar.gz |
compat: helper for detecting unsigned overflow
The idiom (a + b < a) works fine for detecting that an unsigned
integer has overflowed, but a more explicit
unsigned_add_overflows(a, b)
might be easier to read.
Define such a macro, expanding roughly to ((a) < UINT_MAX - (b)).
Because the expansion uses each argument only once outside of sizeof()
expressions, it is safe to use with arguments that have side effects.
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | git-compat-util.h | 6 | ||||
-rw-r--r-- | patch-delta.c | 2 | ||||
-rw-r--r-- | strbuf.c | 5 | ||||
-rw-r--r-- | wrapper.c | 2 |
4 files changed, 11 insertions, 4 deletions
diff --git a/git-compat-util.h b/git-compat-util.h index d6d269f138..9c23622ed5 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -31,6 +31,9 @@ #define maximum_signed_value_of_type(a) \ (INTMAX_MAX >> (bitsizeof(intmax_t) - bitsizeof(a))) +#define maximum_unsigned_value_of_type(a) \ + (UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a))) + /* * Signed integer overflow is undefined in C, so here's a helper macro * to detect if the sum of two integers will overflow. @@ -40,6 +43,9 @@ #define signed_add_overflows(a, b) \ ((b) > maximum_signed_value_of_type(a) - (a)) +#define unsigned_add_overflows(a, b) \ + ((b) > maximum_unsigned_value_of_type(a) - (a)) + #ifdef __GNUC__ #define TYPEOF(x) (__typeof__(x)) #else diff --git a/patch-delta.c b/patch-delta.c index d218faa02b..56e0a5ede2 100644 --- a/patch-delta.c +++ b/patch-delta.c @@ -48,7 +48,7 @@ void *patch_delta(const void *src_buf, unsigned long src_size, if (cmd & 0x20) cp_size |= (*data++ << 8); if (cmd & 0x40) cp_size |= (*data++ << 16); if (cp_size == 0) cp_size = 0x10000; - if (cp_off + cp_size < cp_size || + if (unsigned_add_overflows(cp_off, cp_size) || cp_off + cp_size > src_size || cp_size > size) break; @@ -63,7 +63,8 @@ void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc) void strbuf_grow(struct strbuf *sb, size_t extra) { - if (sb->len + extra + 1 <= sb->len) + if (unsigned_add_overflows(extra, 1) || + unsigned_add_overflows(sb->len, extra + 1)) die("you want to use way too much memory"); if (!sb->alloc) sb->buf = NULL; @@ -152,7 +153,7 @@ int strbuf_cmp(const struct strbuf *a, const struct strbuf *b) void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, const void *data, size_t dlen) { - if (pos + len < pos) + if (unsigned_add_overflows(pos, len)) die("you want to use way too much memory"); if (pos > sb->len) die("`pos' is too far after the end of the buffer"); @@ -53,7 +53,7 @@ void *xmalloc(size_t size) void *xmallocz(size_t size) { void *ret; - if (size + 1 < size) + if (unsigned_add_overflows(size, 1)) die("Data too large to fit into virtual memory space."); ret = xmalloc(size + 1); ((char*)ret)[size] = 0; |