From: Paul Eggert Date: Sun, 30 Jan 2011 07:59:31 +0000 (-0800) Subject: TYPE_MAXIMUM: avoid theoretically undefined behavior X-Git-Tag: v0.1~3271 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=ee9e39c014e2880179c91960ce1f69309d0c1500;p=gnulib.git 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 . * 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. --- diff --git a/ChangeLog b/ChangeLog index f6454e834..da526748a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2011-01-29 Paul Eggert + 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 + . + * 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. diff --git a/lib/intprops.h b/lib/intprops.h index 511a5aa98..58b1b3fbf 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -49,11 +49,11 @@ ? (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. diff --git a/lib/mktime.c b/lib/mktime.c index d35bdd044..248651406 100644 --- a/lib/mktime.c +++ b/lib/mktime.c @@ -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) diff --git a/lib/strtol.c b/lib/strtol.c index 747d70ed3..b6a761ecb 100644 --- a/lib/strtol.c +++ b/lib/strtol.c @@ -141,11 +141,11 @@ ? (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) diff --git a/m4/mktime.m4 b/m4/mktime.m4 index 7836b76ac..56b2416d6 100644 --- a/m4/mktime.m4 +++ b/m4/mktime.m4 @@ -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++) diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4 index 233f1c190..34493bb3a 100644 --- a/m4/nanosleep.m4 +++ b/m4/nanosleep.m4 @@ -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) diff --git a/m4/parse-datetime.m4 b/m4/parse-datetime.m4 index 2341de950..e665ef370 100644 --- a/m4/parse-datetime.m4 +++ b/m4/parse-datetime.m4 @@ -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 /* for time_t */ #include /* 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]; ]])], diff --git a/m4/stdint.m4 b/m4/stdint.m4 index 43e1f7021..26654c68e 100644 --- a/m4/stdint.m4 +++ b/m4/stdint.m4 @@ -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 /* 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)