bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

"date", "uptime" core dumps on huge time stamps (+ "stat" fix)


From: Paul Eggert
Subject: "date", "uptime" core dumps on huge time stamps (+ "stat" fix)
Date: 02 Feb 2004 13:51:38 -0800
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

I just notice that coreutils sometimes calls 'localtime' without
checking that the result is not NULL, which can lead to core dumps on
hosts with 64-bit time_t and 32-bit int (e.g., 64-bit Solaris).  Here
are some fixes.

The "stat" patch doesn't fix a core dump on any host that I know
about, but it's possible on far-future hosts and anyway the fix is
easy.  The stat.c patch also changes the behavior of stat to be nicer
if stat is given time stamps that localtime can't convert.

2004-02-02  Paul Eggert  <address@hidden>

        Don't dump core if localtime returns NULL (possible on
        hosts with 64-bit time_t and 32-bit int).
        * src/date.c: Include "inttostr.h".
        (batch_convert, main):
        If time conversion fails, exit with nonzero status.
        (show_date): Return int to report conversion failure.
        Print the time as an int if localtime fails.
        * src/uptime.c: Print "??" if the current clock can't
        be converted by localtime.  This won't happen until the year
        2*31 + 1900, but we don't want to dump core even if the current
        clock has the wrong value.

        * src/stat.c: Include "inttostr.h".
        (human_time): Print the date/time as a number of seconds since the
        epoch if it can't be converted by localtime.  This is better than
        just saying "invalid", and is consistent with what "ls" does.
        Don't dump core if the year has more than 48 digits; this isn't
        possible on any contemporary host, but we might as well do it right.

Index: src/date.c
===================================================================
RCS file: /home/meyering/coreutils/cu/src/date.c,v
retrieving revision 1.132
diff -p -u -r1.132 date.c
--- src/date.c  21 Jan 2004 22:52:53 -0000      1.132
+++ src/date.c  2 Feb 2004 21:23:30 -0000
@@ -30,6 +30,7 @@
 #include "error.h"
 #include "getdate.h"
 #include "getline.h"
+#include "inttostr.h"
 #include "posixtm.h"
 #include "posixver.h"
 #include "quote.h"
@@ -43,7 +44,7 @@
 
 int putenv ();
 
-static void show_date (const char *format, struct timespec when);
+static int show_date (const char *format, struct timespec when);
 
 enum Time_spec
 {
@@ -271,7 +272,7 @@ batch_convert (const char *input_filenam
        }
       else
        {
-         show_date (format, when);
+         status |= show_date (format, when);
        }
     }
 
@@ -471,7 +472,7 @@ argument must be a format string beginni
            }
        }
 
-      show_date (format, when);
+      status |= show_date (format, when);
     }
 
   exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
@@ -479,9 +480,10 @@ argument must be a format string beginni
 
 /* Display the date and/or time in WHEN according to the format specified
    in FORMAT, followed by a newline.  If FORMAT is NULL, use the
-   standard output format (ctime style but with a timezone inserted). */
+   standard output format (ctime style but with a timezone inserted).
+   Return zero if successful.  */
 
-static void
+static int
 show_date (const char *format, struct timespec when)
 {
   struct tm *tm;
@@ -496,8 +498,6 @@ show_date (const char *format, struct ti
     "%Y-%m-%dT%H:%M:%S%z"
   };
 
-  tm = localtime (&when.tv_sec);
-
   if (format == NULL)
     {
       if (rfc_format)
@@ -520,7 +520,19 @@ show_date (const char *format, struct ti
   else if (*format == '\0')
     {
       printf ("\n");
-      return;
+      return 0;
+    }
+
+  tm = localtime (&when.tv_sec);
+  if (! tm)
+    {
+      char buf[INT_BUFSIZE_BOUND (intmax_t)];
+      error (0, 0, _("time %s is out of range"),
+            (TYPE_SIGNED (time_t)
+             ? imaxtostr (when.tv_sec, buf)
+             : umaxtostr (when.tv_sec, buf)));
+      puts (buf);
+      return 1;
     }
 
   while (1)
@@ -549,4 +561,5 @@ show_date (const char *format, struct ti
 
   printf ("%s\n", out);
   free (out);
+  return 0;
 }
Index: src/stat.c
===================================================================
RCS file: /home/meyering/coreutils/cu/src/stat.c,v
retrieving revision 1.62
diff -p -u -r1.62 stat.c
--- src/stat.c  2 Feb 2004 07:59:58 -0000       1.62
+++ src/stat.c  2 Feb 2004 21:35:58 -0000
@@ -49,6 +49,7 @@
 #include "file-type.h"
 #include "fs.h"
 #include "getopt.h"
+#include "inttostr.h"
 #include "quote.h"
 #include "quotearg.h"
 #include "strftime.h"
@@ -328,13 +329,15 @@ human_access (struct stat const *statbuf
 static char *
 human_time (time_t const *t, int t_ns)
 {
-  static char str[80];
-  struct tm *tm = localtime (t);
+  static char str[MAX (INT_BUFSIZE_BOUND (intmax_t),
+                      (INT_STRLEN_BOUND (int) /* YYYY */
+                       + 1 /* because YYYY might equal INT_MAX + 1900 */
+                       + sizeof "-MM-DD HH:MM:SS.NNNNNNNNN +ZZZZ"))];
+  struct tm const *tm = localtime (t);
   if (tm == NULL)
-    {
-      G_fail = 1;
-      return (char *) _("*** invalid date/time ***");
-    }
+    return (TYPE_SIGNED (time_t)
+           ? imaxtostr (*t, str)
+           : umaxtostr (*t, str));
   nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z", tm, 0, t_ns);
   return str;
 }
Index: src/uptime.c
===================================================================
RCS file: /home/meyering/coreutils/cu/src/uptime.c,v
retrieving revision 1.39
diff -p -u -r1.39 uptime.c
--- src/uptime.c        21 Jan 2004 23:49:37 -0000      1.39
+++ src/uptime.c        2 Feb 2004 21:11:25 -0000
@@ -132,11 +132,14 @@ print_uptime (int n, const STRUCT_UTMP *
   uphours = (uptime - (updays * 86400)) / 3600;
   upmins = (uptime - (updays * 86400) - (uphours * 3600)) / 60;
   tmn = localtime (&time_now);
-  printf (_(" %2d:%02d%s  up "), ((tmn->tm_hour % 12) == 0
-                                 ? 12 : tmn->tm_hour % 12),
-         /* FIXME: use strftime, not am, pm.  Uli reports that
-            the german translation is meaningless.  */
-         tmn->tm_min, (tmn->tm_hour < 12 ? _("am") : _("pm")));
+  if (tmn)
+    printf (_(" %2d:%02d%s  up "),
+           ((tmn->tm_hour % 12) == 0 ? 12 : tmn->tm_hour % 12),
+           /* FIXME: use strftime, not am, pm.  Uli reports that
+              the german translation is meaningless.  */
+           tmn->tm_min, (tmn->tm_hour < 12 ? _("am") : _("pm")));
+  else
+    printf (_(" ??:????  up "));
   if (updays > 0)
     printf (ngettext("%d day", "%d days", updays), updays);
   printf (" %2d:%02d,  ", uphours, upmins);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]