summaryrefslogtreecommitdiff
path: root/lib/libutil
diff options
context:
space:
mode:
authordholland <dholland@NetBSD.org>2015-12-31 10:52:06 +0000
committerdholland <dholland@NetBSD.org>2015-12-31 10:52:06 +0000
commitf6559439593b404e953bb657c19d341c71ad8213 (patch)
treebfdaad430dcbbe89dbd8b6b073f8721be53e7f7f /lib/libutil
parentcbfd5769f63571cf97e14983a861295326374887 (diff)
When computing relative months, use mktime() directly and don't call
our Convert(). And check it for failure. This fixes three sets of problems: (1) depending on the passed-in value of Timezone it might disassemble the time in one timezone and reassemble it in another, causing mysterious offsets of a few hours; (2) with the previous set of changes to this file, Convert() fails if it ends up normalizing a date, so e.g. going three months forward from March 31 would fail; (3) previously if Convert() failed we passed -1 on to DSTcorrect(), which made a mess. PR 50574.
Diffstat (limited to 'lib/libutil')
-rw-r--r--lib/libutil/parsedate.y28
1 files changed, 20 insertions, 8 deletions
diff --git a/lib/libutil/parsedate.y b/lib/libutil/parsedate.y
index dd0335e1ebf..2ae41c7b147 100644
--- a/lib/libutil/parsedate.y
+++ b/lib/libutil/parsedate.y
@@ -14,7 +14,7 @@
#include <sys/cdefs.h>
#ifdef __RCSID
-__RCSID("$NetBSD: parsedate.y,v 1.26 2015/12/31 10:31:07 dholland Exp $");
+__RCSID("$NetBSD: parsedate.y,v 1.27 2015/12/31 10:52:06 dholland Exp $");
#endif
#include <stdio.h>
@@ -728,19 +728,31 @@ RelativeMonth(
{
struct tm tm;
time_t Month;
- time_t Year;
+ time_t Then;
if (RelMonth == 0)
return 0;
+ /*
+ * It doesn't matter what timezone we use to do this computation,
+ * as long as we use the same one to reassemble the time that we
+ * used to disassemble it. So always use localtime and mktime. In
+ * particular, don't use Convert() to reassemble, because it will
+ * not only reassemble with the wrong timezone but it will also
+ * fail if we do e.g. three months from March 31 yielding July 1.
+ */
+ (void)Timezone;
+
if (localtime_r(&Start, &tm) == NULL)
return -1;
+
Month = 12 * (tm.tm_year + 1900) + tm.tm_mon + RelMonth;
- Year = Month / 12;
- Month = Month % 12 + 1;
- return DSTcorrect(Start,
- Convert(Month, (time_t)tm.tm_mday, Year,
- (time_t)tm.tm_hour, (time_t)tm.tm_min, (time_t)tm.tm_sec,
- Timezone, MER24, DSTmaybe));
+ tm.tm_year = (Month / 12) - 1900;
+ tm.tm_mon = Month % 12;
+ errno = 0;
+ Then = mktime(&tm);
+ if (Then == -1 && errno != 0)
+ return -1;
+ return DSTcorrect(Start, Then);
}