Blame SOURCES/0001-Fix-CVE-2016-2315-CVE-2016-2324.patch

fdd391
From 73b65b02d5d1aa4612bb7015f80c8cd1b5e828cd Mon Sep 17 00:00:00 2001
fdd391
From: Petr Stodulka <pstodulk@redhat.com>
fdd391
Date: Fri, 18 Mar 2016 17:14:32 +0100
fdd391
Subject: [PATCH] Fix CVE-2016-2315 CVE-2016-2324
fdd391
fdd391
- added upstream macros for detecting size_t overflow (much more just
fdd391
  for easier related changes in future, if we want to do some yet)
fdd391
- upstream solution removes function path_name() and modify all related
fdd391
  part of code to replace this function. However, it's too hard for
fdd391
  backport to such old version of git without unchanged behaviour,
fdd391
  so application just die with error message instead.
fdd391
---
fdd391
 diff.h            |  4 ++--
fdd391
 git-compat-util.h | 35 +++++++++++++++++++++++++++++++++++
fdd391
 revision.c        | 13 ++++++++++---
fdd391
 3 files changed, 47 insertions(+), 5 deletions(-)
fdd391
fdd391
diff --git a/diff.h b/diff.h
fdd391
index ce123fa..88db230 100644
fdd391
--- a/diff.h
fdd391
+++ b/diff.h
fdd391
@@ -209,8 +209,8 @@ struct combine_diff_path {
fdd391
 	} parent[FLEX_ARRAY];
fdd391
 };
fdd391
 #define combine_diff_path_size(n, l) \
fdd391
-	(sizeof(struct combine_diff_path) + \
fdd391
-	 sizeof(struct combine_diff_parent) * (n) + (l) + 1)
fdd391
+	st_add4(sizeof(struct combine_diff_path), (l), 1, \
fdd391
+		st_mult(sizeof(struct combine_diff_parent), (n)))
fdd391
 
fdd391
 extern void show_combined_diff(struct combine_diff_path *elem, int num_parent,
fdd391
 			      int dense, struct rev_info *);
fdd391
diff --git a/git-compat-util.h b/git-compat-util.h
fdd391
index d493a8c..d5a15fa 100644
fdd391
--- a/git-compat-util.h
fdd391
+++ b/git-compat-util.h
fdd391
@@ -46,6 +46,14 @@
fdd391
 #define unsigned_add_overflows(a, b) \
fdd391
     ((b) > maximum_unsigned_value_of_type(a) - (a))
fdd391
 
fdd391
+/*
fdd391
+ * Returns true if the multiplication of "a" and "b" will
fdd391
+ * overflow. The types of "a" and "b" must match and must be unsigned.
fdd391
+ * Note that this macro evaluates "a" twice!
fdd391
+ */
fdd391
+#define unsigned_mult_overflows(a, b) \
fdd391
+    ((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
fdd391
+
fdd391
 #ifdef __GNUC__
fdd391
 #define TYPEOF(x) (__typeof__(x))
fdd391
 #else
fdd391
@@ -526,6 +534,33 @@ extern void release_pack_memory(size_t);
fdd391
 typedef void (*try_to_free_t)(size_t);
fdd391
 extern try_to_free_t set_try_to_free_routine(try_to_free_t);
fdd391
 
fdd391
+static inline size_t st_add(size_t a, size_t b)
fdd391
+{
fdd391
+	if (unsigned_add_overflows(a, b))
fdd391
+		die("size_t overflow: %"PRIuMAX" + %"PRIuMAX,
fdd391
+		    (uintmax_t)a, (uintmax_t)b);
fdd391
+	return a + b;
fdd391
+}
fdd391
+#define st_add3(a,b,c)   st_add((a),st_add((b),(c)))
fdd391
+#define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d)))
fdd391
+
fdd391
+static inline size_t st_mult(size_t a, size_t b)
fdd391
+{
fdd391
+	if (unsigned_mult_overflows(a, b))
fdd391
+		die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
fdd391
+		    (uintmax_t)a, (uintmax_t)b);
fdd391
+	return a * b;
fdd391
+}
fdd391
+
fdd391
+static inline size_t st_sub(size_t a, size_t b)
fdd391
+{
fdd391
+	if (a < b)
fdd391
+		die("size_t underflow: %"PRIuMAX" - %"PRIuMAX,
fdd391
+		    (uintmax_t)a, (uintmax_t)b);
fdd391
+	return a - b;
fdd391
+}
fdd391
+
fdd391
+
fdd391
 extern char *xstrdup(const char *str);
fdd391
 extern void *xmalloc(size_t size);
fdd391
 extern void *xmallocz(size_t size);
fdd391
diff --git a/revision.c b/revision.c
fdd391
index f40ccf1..b897ca6 100644
fdd391
--- a/revision.c
fdd391
+++ b/revision.c
fdd391
@@ -24,16 +24,21 @@ char *path_name(const struct name_path *path, const char *name)
fdd391
 {
fdd391
 	const struct name_path *p;
fdd391
 	char *n, *m;
fdd391
-	int nlen = strlen(name);
fdd391
-	int len = nlen + 1;
fdd391
+	size_t nlen = strlen(name);
fdd391
+	size_t len = st_add(nlen, 1);
fdd391
+
fdd391
+	if(len >= INT_MAX)
fdd391
+		die("path_name(): path is too long.");
fdd391
 
fdd391
 	for (p = path; p; p = p->up) {
fdd391
 		if (p->elem_len)
fdd391
 			len += p->elem_len + 1;
fdd391
+			if(len >= INT_MAX)
fdd391
+				die("path_name(): path is too long.");
fdd391
 	}
fdd391
 	n = xmalloc(len);
fdd391
 	m = n + len - (nlen + 1);
fdd391
-	strcpy(m, name);
fdd391
+	memcpy(m, name, nlen + 1);
fdd391
 	for (p = path; p; p = p->up) {
fdd391
 		if (p->elem_len) {
fdd391
 			m -= p->elem_len + 1;
fdd391
-- 
fdd391
2.4.3
fdd391