TYPE_MAXIMUM: avoid theoretically undefined behavior
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 30 Jan 2011 07:59:31 +0000 (23:59 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 30 Jan 2011 08:00:00 +0000 (00:00 -0800)
* lib/intprops.h (TYPE_MINIMUM, TYPE_MAXIMUM): Do not shift a
negative number, which the C Standard says has undefined behavior.
In practice this is not a problem, but might as well do it by the book.
Reported by Rich Felker and Eric Blake; see
<http://lists.gnu.org/archive/html/bug-gnulib/2011-01/msg00493.html>.
* lib/strtol.c (TYPE_MINIMUM, TYPE_MAXIMUM): Likewise.
* m4/mktime.m4 (AC_FUNC_MKTIME): Likewise.
* m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): Likewise.
* m4/parse-datetime.m4 (gl_PARSE_DATETIME): Likewise.
* m4/stdint.m4 (gl_STDINT_H): Likewise.
* lib/mktime.c (TYPE_MAXIMUM): Redo slightly to match the others.

ChangeLog
lib/intprops.h
lib/mktime.c
lib/strtol.c
m4/mktime.m4
m4/nanosleep.m4
m4/parse-datetime.m4
m4/stdint.m4

index f6454e8..da52674 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2011-01-29  Paul Eggert  <eggert@cs.ucla.edu>
 
+       TYPE_MAXIMUM: avoid theoretically undefined behavior
+       * lib/intprops.h (TYPE_MINIMUM, TYPE_MAXIMUM): Do not shift a
+       negative number, which the C Standard says has undefined behavior.
+       In practice this is not a problem, but might as well do it by the book.
+       Reported by Rich Felker and Eric Blake; see
+       <http://lists.gnu.org/archive/html/bug-gnulib/2011-01/msg00493.html>.
+       * lib/strtol.c (TYPE_MINIMUM, TYPE_MAXIMUM): Likewise.
+       * m4/mktime.m4 (AC_FUNC_MKTIME): Likewise.
+       * m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): Likewise.
+       * m4/parse-datetime.m4 (gl_PARSE_DATETIME): Likewise.
+       * m4/stdint.m4 (gl_STDINT_H): Likewise.
+       * lib/mktime.c (TYPE_MAXIMUM): Redo slightly to match the others.
+
        mktime: #undef mktime before #defining it
        * lib/mktime.c (mktime) [DEBUG]: #undef mktime before #defining it.
 
index 511a5aa..58b1b3f 100644 (file)
         ? (t) 0 \
         : TYPE_SIGNED_MAGNITUDE (t) \
         ? ~ (t) 0 \
-        : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+        : ~ TYPE_MAXIMUM (t)))
 # define TYPE_MAXIMUM(t) \
   ((t) (! TYPE_SIGNED (t) \
         ? (t) -1 \
-        : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+        : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
 
 /* Return zero if T can be determined to be an unsigned type.
    Otherwise, return 1.
index d35bdd0..2486514 100644 (file)
@@ -113,7 +113,7 @@ typedef long long int long_int;
 #define TYPE_MAXIMUM(t) \
   ((t) (! TYPE_SIGNED (t) \
         ? (t) -1 \
-        : (((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) << 1) + 1)))
+        : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
 
 #ifndef TIME_T_MIN
 # define TIME_T_MIN TYPE_MINIMUM (time_t)
index 747d70e..b6a761e 100644 (file)
          ? (t) 0 \
          : TYPE_SIGNED_MAGNITUDE (t) \
          ? ~ (t) 0 \
-         : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+         : ~ TYPE_MAXIMUM (t)))
 # define TYPE_MAXIMUM(t) \
    ((t) (! TYPE_SIGNED (t) \
          ? (t) -1 \
-         : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+         : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
 
 # ifndef ULLONG_MAX
 #  define ULLONG_MAX TYPE_MAXIMUM (unsigned long long)
index 7836b76..56b2416 100644 (file)
@@ -1,4 +1,4 @@
-# serial 18
+# serial 19
 dnl Copyright (C) 2002-2003, 2005-2007, 2009-2011 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
@@ -175,12 +175,13 @@ main ()
 
   time_t_max = (! time_t_signed
                 ? (time_t) -1
-                : ~ (~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)));
+                : ((((time_t) 1 << (sizeof (time_t) * CHAR_BIT - 2)) - 1)
+                   * 2 + 1));
   time_t_min = (! time_t_signed
                 ? (time_t) 0
                 : time_t_signed_magnitude
                 ? ~ (time_t) 0
-                : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1));
+                : ~ time_t_max);
 
   delta = time_t_max / 997; /* a suitable prime number */
   for (i = 0; i < N_STRINGS; i++)
index 233f1c1..34493bb 100644 (file)
@@ -1,4 +1,4 @@
-# serial 32
+# serial 33
 
 dnl From Jim Meyering.
 dnl Check for the nanosleep function.
@@ -58,7 +58,7 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
           #define TYPE_MAXIMUM(t) \
             ((t) (! TYPE_SIGNED (t) \
                   ? (t) -1 \
-                  : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+                  : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
 
           static void
           check_for_SIGALRM (int sig)
index 2341de9..e665ef3 100644 (file)
@@ -1,4 +1,4 @@
-# parse-datetime.m4 serial 18
+# parse-datetime.m4 serial 19
 dnl Copyright (C) 2002-2006, 2008-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -41,9 +41,11 @@ AC_DEFUN([gl_PARSE_DATETIME],
 #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)))
+  ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ TYPE_MAXIMUM (t)))
 #define TYPE_MAXIMUM(t) \
-  ((t) ((t) 0 < (t) -1 ? (t) -1 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+  ((t) ((t) 0 < (t) -1 \
+        ? (t) -1 \
+        : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 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];
        ]])],
index 43e1f70..26654c6 100644 (file)
@@ -1,4 +1,4 @@
-# stdint.m4 serial 36
+# stdint.m4 serial 37
 dnl Copyright (C) 2001-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -145,9 +145,11 @@ uintmax_t j = UINTMAX_MAX;
 
 #include <limits.h> /* for CHAR_BIT */
 #define TYPE_MINIMUM(t) \
-  ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+  ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ TYPE_MAXIMUM (t)))
 #define TYPE_MAXIMUM(t) \
-  ((t) ((t) 0 < (t) -1 ? (t) -1 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+  ((t) ((t) 0 < (t) -1 \
+        ? (t) -1 \
+        : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
 struct s {
   int check_PTRDIFF:
       PTRDIFF_MIN == TYPE_MINIMUM (ptrdiff_t)