git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] compat: helper for detecting unsigned overflow

From
Jonathan Nieder <jrnieder@gmail.com>
Date
Feb 10, 2011, 09:35 UTC
Message-ID
<20110210093536.GB365@elie>
In-Reply-To
<1286263450-5372-1-git-send-email-kusmabite@gmail.com>
Date: Sun, 10 Oct 2010 21:59:26 -0500

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>
---
From the svn remote helper project.  Sane?
 git-compat-util.h |    6 ++++++
 patch-delta.c     |    2 +-
 strbuf.c          |    5 +++--
 wrapper.c         |    2 +-
 4 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/git-compat-util.h b/git-compat-util.h
index d6d269f..9c23622 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 d218faa..56e0a5e 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;
diff --git a/strbuf.c b/strbuf.c
index 9b3c445..07e8883 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -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");
diff --git a/wrapper.c b/wrapper.c
index 55b074e..4c147d6 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -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;
-- 
1.7.4
Previous: Nicolas PitreNext: Sverre Rabbelier
Message 3 of 5 in “do not depend on signed integer overflow”
  1. do not depend on signed integer overflowErik Faye-Lund, Oct 5, 2010
  2. Nicolas PitreOct 5, 2010
  3. compat: helper for detecting unsigned overflowJonathan Nieder, Feb 10, 2011
  4. Sverre RabbelierFeb 10, 2011
  5. Joshua JuranFeb 10, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.