date: check date overflow against time_t

When we check whether a timestamp has overflowed, we check only against ULONG_MAX, meaning that strtoul has overflowed. However, we also feed these timestamps to system functions like gmtime, which expect a time_t. On many systems, time_t is actually smaller than "unsigned long" (e.g., because it is signed), and we would overflow when using these functions. We don't know the actual size or signedness of time_t, but we can easily check for truncation with a simple assignment. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Feb 24, 2014 at 02:39 UTC 7ca36d9398a85e7974d04f8fbd2c6adb088290e1
3 files changed +19 -1
cache.h
+1
@@ -909,6 +909,7 @@ void datestamp(char *buf, int bufsize);
909 unsigned long approxidate_careful(const char *, int *);
910 unsigned long approxidate_relative(const char *date, const struct timeval *now);
911 enum date_mode parse_date_format(const char *format);
912 +int date_overflows(unsigned long date);
913
914 #define IDENT_STRICT 1
915 #define IDENT_NO_DATE 2
date.c
+17
@@ -1085,3 +1085,20 @@ unsigned long approxidate_careful(const char *date, int *error_ret)
1085 gettimeofday(&tv, NULL);
1086 return approxidate_str(date, &tv, error_ret);
1087 }
1088 +
1089 +int date_overflows(unsigned long t)
1090 +{
1091 + time_t sys;
1092 +
1093 + /* If we overflowed our unsigned long, that's bad... */
1094 + if (t == ULONG_MAX)
1095 + return 1;
1096 +
1097 + /*
1098 + * ...but we also are going to feed the result to system
1099 + * functions that expect time_t, which is often "signed long".
1100 + * Make sure that we fit into time_t, as well.
1101 + */
1102 + sys = t;
1103 + return t != sys || (t < 1) != (sys < 1);
1104 +}
fsck.c
+1 -1
@@ -266,7 +266,7 @@ static int fsck_ident(char **ident, struct object *obj, fsck_error error_func)
266 (*ident)++;
267 if (**ident == '0' && (*ident)[1] != ' ')
268 return error_func(obj, FSCK_ERROR, "invalid author/committer line - zero-padded date");
269 - if (strtoul(*ident, &end, 10) == ULONG_MAX)
269 + if (date_overflows(strtoul(*ident, &end, 10)))
270 return error_func(obj, FSCK_ERROR, "invalid author/committer line - date causes integer overflow");
271 if (end == *ident || *end != ' ')
272 return error_func(obj, FSCK_ERROR, "invalid author/committer line - bad date");