bug-gnulib
[Top][All Lists]
Advanced

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

Re: time_t on NetBSD/i386


From: Bruno Haible
Subject: Re: time_t on NetBSD/i386
Date: Thu, 17 Sep 2009 09:38:27 +0200
User-agent: KMail/1.9.9

Hasso Tepper wrote:
> time_t is 64 bits in recent NetBSD versions even on i386 platform, 
> therefore these assertations fail on it:
> 
> in lib/mktime.c:
> verify (long_int_year_and_yday_are_wide_enough,
>     INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX);

I'm disabling this assertion; the code seems to be correct also with
64-bit 'time_t'.

> in lib/getdate.y:
> verify (LONG_MIN <= TYPE_MINIMUM (time_t) && TYPE_MAXIMUM (time_t) <= 
>     LONG_MAX);

This one is harder. It has already been reported for QNX [1][2].
[1] http://lists.gnu.org/archive/html/bug-gnulib/2008-01/msg00161.html
[2] http://lists.gnu.org/archive/html/bug-gnulib/2009-07/msg00111.html

Here is a proposed patch. I checked all uses of 'time_t' in getdate.y and
found only two conversions from time_t to 'long int', in the 'relunit' rule:

  | tSDECIMAL_NUMBER tSEC_UNIT
      { $$ = RELATIVE_TIME_0; $$.seconds = $1.tv_sec; $$.ns = $1.tv_nsec; }
  | tUDECIMAL_NUMBER tSEC_UNIT
      { $$ = RELATIVE_TIME_0; $$.seconds = $1.tv_sec; $$.ns = $1.tv_nsec; }

So this patch should handle it. Jim, Eric, opinions?


2009-09-17  Bruno Haible  <address@hidden>

        Make getdate.y compile on QNX and NetBSD 5 / i386.
        * m4/getdate.m4 (gl_GETDATE): Conditionally define
        TIME_T_FITS_IN_LONG_INT.
        * lib/getdate.y (long_time_t): New type.
        (relative_time): Change type of 'seconds' field to long_time_t.
        (get_date): Update types of local variables. Check against overflow
        during conversion from long_time_t to time_t.
        Reported by Matt Kraai <address@hidden>
        and Hasso Tepper <address@hidden>.

--- m4/getdate.m4.orig  2009-09-17 09:28:32.000000000 +0200
+++ m4/getdate.m4       2009-09-17 08:35:40.000000000 +0200
@@ -1,4 +1,4 @@
-# getdate.m4 serial 15
+# getdate.m4 serial 16
 dnl Copyright (C) 2002-2006, 2008, 2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -36,4 +36,18 @@
   AC_STRUCT_TIMEZONE
   AC_REQUIRE([gl_CLOCK_TIME])
   AC_REQUIRE([gl_TM_GMTOFF])
+  AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE([[
+#include <time.h> /* for time_t */
+#include <limits.h> /* for CHAR_BIT, LONG_MIN, LONG_MAX */
+#define TYPE_MINIMUM(t) \
+  ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+#define TYPE_MAXIMUM(t) \
+  ((t) ((t) 0 < (t) -1 ? (t) -1 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+typedef int verify_min[2 * (LONG_MIN <= TYPE_MINIMUM (time_t)) - 1];
+typedef int verify_max[2 * (TYPE_MAXIMUM (time_t) <= LONG_MAX) - 1];
+       ]])],
+    [AC_DEFINE([TIME_T_FITS_IN_LONG_INT], [1],
+       [Define to 1 if all 'time_t' values fit in a 'long int'.])
+    ])
 ])
--- lib/getdate.y.orig  2009-09-17 09:28:32.000000000 +0200
+++ lib/getdate.y       2009-09-17 09:24:49.000000000 +0200
@@ -108,12 +108,21 @@
 
 #define HOUR(x) ((x) * 60)
 
-/* Lots of this code assumes time_t and time_t-like values fit into
-   long int.  It also assumes that signed integer overflow silently
-   wraps around, but there's no portable way to check for that at
-   compile-time.  */
+/* long_time_t is a signed integer type that contains all time_t values.  */
 verify (TYPE_IS_INTEGER (time_t));
-verify (LONG_MIN <= TYPE_MINIMUM (time_t) && TYPE_MAXIMUM (time_t) <= 
LONG_MAX);
+#if TIME_T_FITS_IN_LONG_INT
+typedef long int long_time_t;
+#else
+typedef time_t long_time_t;
+#endif
+
+/* Lots of this code assumes time_t and time_t-like values fit into
+   long_time_t.  */
+verify (TYPE_MINIMUM (long_time_t) <= TYPE_MINIMUM (time_t)
+        && TYPE_MAXIMUM (time_t) <= TYPE_MAXIMUM (long_time_t));
+
+/* FIXME: It also assumes that signed integer overflow silently wraps around,
+   but this is not true any more with recent versions of GCC 4.  */
 
 /* An integer value, and the number of digits in its textual
    representation.  */
@@ -146,7 +155,7 @@
   long int day;
   long int hour;
   long int minutes;
-  long int seconds;
+  long_time_t seconds;
   long int ns;
 } relative_time;
 
@@ -1502,20 +1511,22 @@
        time_t t1 = t0 + d1;
        long int d2 = 60 * pc.rel.minutes;
        time_t t2 = t1 + d2;
-       long int d3 = pc.rel.seconds;
-       time_t t3 = t2 + d3;
+       long_time_t d3 = pc.rel.seconds;
+       long_time_t t3 = t2 + d3;
        long int d4 = (sum_ns - normalized_ns) / BILLION;
-       time_t t4 = t3 + d4;
+       long_time_t t4 = t3 + d4;
+       time_t t5 = t4;
 
        if ((d1 / (60 * 60) ^ pc.rel.hour)
            | (d2 / 60 ^ pc.rel.minutes)
            | ((t1 < t0) ^ (d1 < 0))
            | ((t2 < t1) ^ (d2 < 0))
            | ((t3 < t2) ^ (d3 < 0))
-           | ((t4 < t3) ^ (d4 < 0)))
+           | ((t4 < t3) ^ (d4 < 0))
+           | (t5 != t4))
          goto fail;
 
-       result->tv_sec = t4;
+       result->tv_sec = t5;
        result->tv_nsec = normalized_ns;
       }
     }




reply via email to

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