* gmt_mktime.c (gmt_mktime): Handle years earlier than 1970.
authorKen Raeburn <raeburn@mit.edu>
Mon, 5 Mar 2001 20:48:43 +0000 (20:48 +0000)
committerKen Raeburn <raeburn@mit.edu>
Mon, 5 Mar 2001 20:48:43 +0000 (20:48 +0000)
(main) [TEST_LEAP]: New routine, driver for testing.
* Makefile.in (t_mktime): New target.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13055 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/os/ChangeLog
src/lib/krb5/os/Makefile.in
src/lib/krb5/os/gmt_mktime.c

index acfbdf5b1dda9aefb2cd46d5e32368691346aae1..92e14c5647fb4af7537e33a729dc283005f059e4 100644 (file)
@@ -1,3 +1,9 @@
+2001-03-05  Ken Raeburn  <raeburn@mit.edu>
+
+       * gmt_mktime.c (gmt_mktime): Handle years earlier than 1970.
+       (main) [TEST_LEAP]: New routine, driver for testing.
+       * Makefile.in (t_mktime): New target.
+
 2001-03-05  Sam Hartman  <hartmans@mit.edu>
 
        * kuserok.c: Set max_username to 65 not 10.  65 should be enough
@@ -61,7 +67,6 @@
        krb5_skdc_timeout_1. (moved to os-proto.h). Cast arguments to int
        for send() and recv().
 
-
 2000-10-09  Ken Raeburn  <raeburn@mit.edu>
 
        Support for getifaddrs() interface added in BSD.
index 3b22ed30e826fe19339f75ed2685583f6892ad69..70faf78337783ae9bd0472baf7dc8be0ddb90ece 100644 (file)
@@ -166,6 +166,9 @@ t_an_to_ln: $(T_AN_TO_LN_OBJS) $(KRB5_BASE_DEPLIBS)
 t_realm_iter: $(T_REALM_ITER_OBJS) $(KRB5_BASE_DEPLIBS)
        $(CC_LINK) -o t_realm_iter $(T_REALM_ITER_OBJS) $(KRB5_BASE_LIBS)
 
+t_mktime: gmt_mktime.c
+       $(CC) $(ALL_CFLAGS) -DTEST_LEAP -o t_mktime $(srcdir)/gmt_mktime.c
+
 t_localaddr: localaddr.c
        $(CC) $(ALL_CFLAGS) -DTEST -o t_localaddr $(srcdir)/localaddr.c
 LCLINT=lclint
index 1e3eebd1a05c6b0bf8e4813c79067585fa0938d9..d0053adfd4a0ce5598c6672dc7d7e61f298b825f 100644 (file)
@@ -43,8 +43,18 @@ time_t gmt_mktime(t)
 
 #define assert_time(cnd) if(!(cnd)) return (time_t) -1
 
-  assert_time(t->tm_year>=70);
+  /*
+   * For 32-bit signed time_t centered on 1/1/1970, the range is:
+   * time 0x80000000 -> Fri Dec 13 16:45:52 1901
+   * time 0x7fffffff -> Mon Jan 18 22:14:07 2038
+   *
+   * So years 1901 and 2038 are allowable, but we can't encode all
+   * dates in those years, and we're not doing overflow/underflow
+   * checking for such cases.
+   */
+  assert_time(t->tm_year>=1);
   assert_time(t->tm_year<=138);
+
   assert_time(t->tm_mon>=0);
   assert_time(t->tm_mon<=11);
   assert_time(t->tm_mday>=1);
@@ -63,7 +73,10 @@ time_t gmt_mktime(t)
   accum *= 365;                        /* 365 days/normal year */
 
   /* add in leap day for all previous years */
-  accum += (t->tm_year - 69) / 4;
+  if (t->tm_year >= 70)
+    accum += (t->tm_year - 69) / 4;
+  else
+    accum -= (72 - t->tm_year) / 4;
   /* add in leap day for this year */
   if(t->tm_mon >= 2)           /* march or later */
     if(hasleapday((t->tm_year + 1900))) accum += 1;
@@ -79,3 +92,37 @@ time_t gmt_mktime(t)
 
   return accum;
 }
+
+#ifdef TEST_LEAP
+int
+main (int argc, char *argv[])
+{
+  int yr;
+  time_t t;
+  struct tm tm = {
+    .tm_mon = 0, .tm_mday = 1,
+    .tm_hour = 0, .tm_min = 0, .tm_sec = 0,
+  };
+  for (yr = 60; yr <= 104; yr++)
+    {
+      printf ("1/1/%d%c -> ", 1900 + yr, hasleapday((1900+yr)) ? '*' : ' ');
+      tm.tm_year = yr;
+      t = gmt_mktime (&tm);
+      if (t == (time_t) -1)
+       printf ("-1\n");
+      else
+       {
+         long u;
+         if (t % (24 * 60 * 60))
+           printf ("(not integral multiple of days) ");
+         u = t / (24 * 60 * 60);
+         printf ("%3ld*365%+ld\t0x%08lx\n",
+                 (long) (u / 365), (long) (u % 365),
+                 (long) t);
+       }
+    }
+  t = 0x80000000, printf ("time 0x%lx -> %s", t, ctime (&t));
+  t = 0x7fffffff, printf ("time 0x%lx -> %s", t, ctime (&t));
+  return 0;
+}
+#endif