summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git-compat-util.h34
1 files changed, 34 insertions, 0 deletions
diff --git a/git-compat-util.h b/git-compat-util.h
index af5af22680..061e33c774 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -96,6 +96,14 @@
#define unsigned_add_overflows(a, b) \
((b) > maximum_unsigned_value_of_type(a) - (a))
+/*
+ * Returns true if the multiplication of "a" and "b" will
+ * overflow. The types of "a" and "b" must match and must be unsigned.
+ * Note that this macro evaluates "a" twice!
+ */
+#define unsigned_mult_overflows(a, b) \
+ ((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
+
#ifdef __GNUC__
#define TYPEOF(x) (__typeof__(x))
#else
@@ -698,6 +706,32 @@ extern void release_pack_memory(size_t);
typedef void (*try_to_free_t)(size_t);
extern try_to_free_t set_try_to_free_routine(try_to_free_t);
+static inline size_t st_add(size_t a, size_t b)
+{
+ if (unsigned_add_overflows(a, b))
+ die("size_t overflow: %"PRIuMAX" + %"PRIuMAX,
+ (uintmax_t)a, (uintmax_t)b);
+ return a + b;
+}
+#define st_add3(a,b,c) st_add((a),st_add((b),(c)))
+#define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d)))
+
+static inline size_t st_mult(size_t a, size_t b)
+{
+ if (unsigned_mult_overflows(a, b))
+ die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
+ (uintmax_t)a, (uintmax_t)b);
+ return a * b;
+}
+
+static inline size_t st_sub(size_t a, size_t b)
+{
+ if (a < b)
+ die("size_t underflow: %"PRIuMAX" - %"PRIuMAX,
+ (uintmax_t)a, (uintmax_t)b);
+ return a - b;
+}
+
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
# define xalloca(size) (alloca(size))