summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cache.h1
-rw-r--r--date.c17
-rw-r--r--fsck.c2
3 files changed, 19 insertions, 1 deletions
diff --git a/cache.h b/cache.h
index bb71bf8a7f..9a2c377b73 100644
--- a/cache.h
+++ b/cache.h
@@ -909,6 +909,7 @@ void datestamp(char *buf, int bufsize);
unsigned long approxidate_careful(const char *, int *);
unsigned long approxidate_relative(const char *date, const struct timeval *now);
enum date_mode parse_date_format(const char *format);
+int date_overflows(unsigned long date);
#define IDENT_STRICT 1
#define IDENT_NO_DATE 2
diff --git a/date.c b/date.c
index 57331ed406..2dae471dd1 100644
--- a/date.c
+++ b/date.c
@@ -1085,3 +1085,20 @@ unsigned long approxidate_careful(const char *date, int *error_ret)
gettimeofday(&tv, NULL);
return approxidate_str(date, &tv, error_ret);
}
+
+int date_overflows(unsigned long t)
+{
+ time_t sys;
+
+ /* If we overflowed our unsigned long, that's bad... */
+ if (t == ULONG_MAX)
+ return 1;
+
+ /*
+ * ...but we also are going to feed the result to system
+ * functions that expect time_t, which is often "signed long".
+ * Make sure that we fit into time_t, as well.
+ */
+ sys = t;
+ return t != sys || (t < 1) != (sys < 1);
+}
diff --git a/fsck.c b/fsck.c
index 760e072cce..64bf279fd7 100644
--- a/fsck.c
+++ b/fsck.c
@@ -266,7 +266,7 @@ static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
(*ident)++;
if (**ident == '0' && (*ident)[1] != ' ')
return error_func(obj, FSCK_ERROR, "invalid author/committer line - zero-padded date");
- if (strtoul(*ident, &end, 10) == ULONG_MAX)
+ if (date_overflows(strtoul(*ident, &end, 10)))
return error_func(obj, FSCK_ERROR, "invalid author/committer line - date causes integer overflow");
if (end == *ident || *end != ' ')
return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad date");