Browse Source

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>
maint
Jeff King 11 years ago committed by Junio C Hamano
parent
commit
7ca36d9398
  1. 1
      cache.h
  2. 17
      date.c
  3. 2
      fsck.c

1
cache.h

@ -909,6 +909,7 @@ void datestamp(char *buf, int bufsize); @@ -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

17
date.c

@ -1085,3 +1085,20 @@ unsigned long approxidate_careful(const char *date, int *error_ret) @@ -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);
}

2
fsck.c

@ -266,7 +266,7 @@ static int fsck_ident(char **ident, struct object *obj, fsck_error error_func) @@ -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");

Loading…
Cancel
Save