Skip to content
This repository
Browse code

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>
  • Loading branch information...
commit 1368f65002bf39fdde7dd736a75ae35475184371 1 parent a8e4a59
jrn jrn authored gitster committed
6 git-compat-util.h
@@ -31,6 +31,9 @@
31 31 #define maximum_signed_value_of_type(a) \
32 32 (INTMAX_MAX >> (bitsizeof(intmax_t) - bitsizeof(a)))
33 33
  34 +#define maximum_unsigned_value_of_type(a) \
  35 + (UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a)))
  36 +
34 37 /*
35 38 * Signed integer overflow is undefined in C, so here's a helper macro
36 39 * to detect if the sum of two integers will overflow.
@@ -40,6 +43,9 @@
40 43 #define signed_add_overflows(a, b) \
41 44 ((b) > maximum_signed_value_of_type(a) - (a))
42 45
  46 +#define unsigned_add_overflows(a, b) \
  47 + ((b) > maximum_unsigned_value_of_type(a) - (a))
  48 +
43 49 #ifdef __GNUC__
44 50 #define TYPEOF(x) (__typeof__(x))
45 51 #else
2  patch-delta.c
@@ -48,7 +48,7 @@ void *patch_delta(const void *src_buf, unsigned long src_size,
48 48 if (cmd & 0x20) cp_size |= (*data++ << 8);
49 49 if (cmd & 0x40) cp_size |= (*data++ << 16);
50 50 if (cp_size == 0) cp_size = 0x10000;
51   - if (cp_off + cp_size < cp_size ||
  51 + if (unsigned_add_overflows(cp_off, cp_size) ||
52 52 cp_off + cp_size > src_size ||
53 53 cp_size > size)
54 54 break;
5 strbuf.c
@@ -63,7 +63,8 @@ void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
63 63
64 64 void strbuf_grow(struct strbuf *sb, size_t extra)
65 65 {
66   - if (sb->len + extra + 1 <= sb->len)
  66 + if (unsigned_add_overflows(extra, 1) ||
  67 + unsigned_add_overflows(sb->len, extra + 1))
67 68 die("you want to use way too much memory");
68 69 if (!sb->alloc)
69 70 sb->buf = NULL;
@@ -152,7 +153,7 @@ int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
152 153 void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
153 154 const void *data, size_t dlen)
154 155 {
155   - if (pos + len < pos)
  156 + if (unsigned_add_overflows(pos, len))
156 157 die("you want to use way too much memory");
157 158 if (pos > sb->len)
158 159 die("`pos' is too far after the end of the buffer");
2  wrapper.c
@@ -53,7 +53,7 @@ void *xmalloc(size_t size)
53 53 void *xmallocz(size_t size)
54 54 {
55 55 void *ret;
56   - if (size + 1 < size)
  56 + if (unsigned_add_overflows(size, 1))
57 57 die("Data too large to fit into virtual memory space.");
58 58 ret = xmalloc(size + 1);
59 59 ((char*)ret)[size] = 0;

0 comments on commit 1368f65

Please sign in to comment.
Something went wrong with that request. Please try again.