Module Name:    src
Committed By:   dholland
Date:           Thu Dec 31 10:52:06 UTC 2015

Modified Files:
        src/lib/libutil: parsedate.y

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/lib/libutil/parsedate.y

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libutil/parsedate.y
diff -u src/lib/libutil/parsedate.y:1.26 src/lib/libutil/parsedate.y:1.27
--- src/lib/libutil/parsedate.y:1.26	Thu Dec 31 10:31:07 2015
+++ src/lib/libutil/parsedate.y	Thu Dec 31 10:52:06 2015
@@ -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);
 }
 
 

Reply via email to