From 7fcec48da90f95dc64268ebd4b3073ae9487fe4e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 15 Apr 2015 08:43:58 -0700 Subject: [PATCH 1/2] parse_date_basic(): return early when given a bogus timestamp When the input does not have GMT timezone offset, the code computes it by computing the local and GMT time for the given timestamp. But there is no point doing so if the given timestamp is known to be a bogus one. Signed-off-by: Junio C Hamano --- date.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/date.c b/date.c index 782de95d90..76fb47518d 100644 --- a/date.c +++ b/date.c @@ -696,6 +696,9 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset) /* mktime uses local timezone */ *timestamp = tm_to_time_t(&tm); + if (*timestamp == -1) + return -1; + if (*offset == -1) { time_t temp_time = mktime(&tm); if ((time_t)*timestamp > temp_time) { @@ -705,9 +708,6 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset) } } - if (*timestamp == -1) - return -1; - if (!tm_gmt) *timestamp -= *offset * 60; return 0; /* success */ From f6e6362107a1e7a798dc1c28ef439a3157813467 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 15 Apr 2015 08:47:48 -0700 Subject: [PATCH 2/2] parse_date_basic(): let the system handle DST conversion The function parses the input to compute the broken-down time in "struct tm", and the GMT timezone offset. If the timezone offset does not exist in the input, the broken-down time is turned into the number of seconds since epoch both in the current timezone and in GMT and the offset is computed as their difference. However, we forgot to make sure tm.tm_isdst is set to -1 (i.e. let the system figure out if DST is in effect in the current timezone when turning the broken-down time to the number of seconds since epoch); it is done so at the beginning of the function, but a call to match_digit() in the function can lead to a call to gmtime_r() to clobber the field. Reported-by: Linus Torvalds Diagnosed-by: Eric Sunshine Signed-off-by: Junio C Hamano --- date.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/date.c b/date.c index 76fb47518d..52a99448d2 100644 --- a/date.c +++ b/date.c @@ -694,13 +694,17 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset) date += match; } - /* mktime uses local timezone */ + /* do not use mktime(), which uses local timezone, here */ *timestamp = tm_to_time_t(&tm); if (*timestamp == -1) return -1; if (*offset == -1) { - time_t temp_time = mktime(&tm); + time_t temp_time; + + /* gmtime_r() in match_digit() may have clobbered it */ + tm.tm_isdst = -1; + temp_time = mktime(&tm); if ((time_t)*timestamp > temp_time) { *offset = ((time_t)*timestamp - temp_time) / 60; } else {