bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH 1/5] Port mktime_internal offset to unsigned time_t


From: Paul Eggert
Subject: [PATCH 1/5] Port mktime_internal offset to unsigned time_t
Date: Sun, 1 May 2016 17:27:24 -0700

This avoids some assumptions about wraparound arithmetic on
signed integer overflow.
* lib/mktime-internal.h (mktime_offset_t): New type.
(mktime_internal): Use it in decl.
* lib/mktime.c, lib/timegm.c (mktime_offset_t) [_LIBC]: New type.
* lib/mktime.c (__mktime_internal, localtime_offset):
* lib/timegm.c (timegm): Use it.
* m4/mktime.m4 (gl_TIME_T_IS_SIGNED): New macro.
(gl_FUNC_MKTIME): Require it.
---
 ChangeLog             | 13 +++++++++++++
 lib/mktime-internal.h | 35 ++++++++++++++++++++++++++++++++++-
 lib/mktime.c          | 12 +++++-------
 lib/timegm.c          |  6 ++++--
 m4/mktime.m4          | 22 ++++++++++++++++++----
 5 files changed, 74 insertions(+), 14 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 09c302c..4b406cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2016-05-01  Paul Eggert  <address@hidden>
+
+       Port mktime_internal offset to unsigned time_t
+       This avoids some assumptions about wraparound arithmetic on
+       signed integer overflow.
+       * lib/mktime-internal.h (mktime_offset_t): New type.
+       (mktime_internal): Use it in decl.
+       * lib/mktime.c, lib/timegm.c (mktime_offset_t) [_LIBC]: New type.
+       * lib/mktime.c (__mktime_internal, localtime_offset):
+       * lib/timegm.c (timegm): Use it.
+       * m4/mktime.m4 (gl_TIME_T_IS_SIGNED): New macro.
+       (gl_FUNC_MKTIME): Require it.
+
 2016-04-27  Paul Eggert  <address@hidden>
 
        xstrtol: prohibit monstrosities like "1bB"
diff --git a/lib/mktime-internal.h b/lib/mktime-internal.h
index 4287acf..0c9e204 100644
--- a/lib/mktime-internal.h
+++ b/lib/mktime-internal.h
@@ -1,4 +1,37 @@
+/* mktime variant that also uses an offset guess
+
+   Copyright 2016 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
 #include <time.h>
+
+/* mktime_offset_t is a signed type wide enough to hold a UTC offset
+   in seconds, and used as part of the type of the offset-guess
+   argument to mktime_internal.  Use time_t on platforms where time_t
+   is signed, to be compatible with platforms like BeOS that export
+   this implementation detail of mktime.  On platforms where time_t is
+   unsigned, GNU and POSIX code can assume 'int' is at least 32 bits
+   which is wide enough for a UTC offset.  */
+
+#if TIME_T_IS_SIGNED
+typedef time_t mktime_offset_t;
+#else
+typedef int mktime_offset_t;
+#endif
+
 time_t mktime_internal (struct tm *,
                         struct tm * (*) (time_t const *, struct tm *),
-                        time_t *);
+                        mktime_offset_t *);
diff --git a/lib/mktime.c b/lib/mktime.c
index 627b1a3..4f4f0bf 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -120,7 +120,9 @@ const unsigned short int __mon_yday[2][13] =
   };
 
 
-#ifndef _LIBC
+#ifdef _LIBC
+typedef time_t mktime_offset_t;
+#else
 /* Portable standalone applications should supply a <time.h> that
    declares a POSIX-compliant localtime_r, for the benefit of older
    implementations that lack localtime_r or have a nonstandard one.
@@ -296,7 +298,7 @@ ranged_convert (struct tm *(*convert) (const time_t *, 
struct tm *),
 time_t
 __mktime_internal (struct tm *tp,
                   struct tm *(*convert) (const time_t *, struct tm *),
-                  time_t *offset)
+                  mktime_offset_t *offset)
 {
   time_t t, gt, t0, t1, t2;
   struct tm tm;
@@ -518,11 +520,7 @@ __mktime_internal (struct tm *tp,
 }
 
 
-/* FIXME: This should use a signed type wide enough to hold any UTC
-   offset in seconds.  'int' should be good enough for GNU code.  We
-   can't fix this unilaterally though, as other modules invoke
-   __mktime_internal.  */
-static time_t localtime_offset;
+static mktime_offset_t localtime_offset;
 
 /* Convert *TP to a time_t value.  */
 time_t
diff --git a/lib/timegm.c b/lib/timegm.c
index 1f567ec..ee9e497 100644
--- a/lib/timegm.c
+++ b/lib/timegm.c
@@ -22,7 +22,9 @@
 
 #include <time.h>
 
-#ifndef _LIBC
+#ifdef _LIBC
+typedef time_t mktime_offset_t;
+#else
 # undef __gmtime_r
 # define __gmtime_r gmtime_r
 # define __mktime_internal mktime_internal
@@ -32,7 +34,7 @@
 time_t
 timegm (struct tm *tmp)
 {
-  static time_t gmtime_offset;
+  static mktime_offset_t gmtime_offset;
   tmp->tm_isdst = 0;
   return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
 }
diff --git a/m4/mktime.m4 b/m4/mktime.m4
index 78f16ba..5a0f2d8 100644
--- a/m4/mktime.m4
+++ b/m4/mktime.m4
@@ -1,4 +1,4 @@
-# serial 25
+# serial 26
 dnl Copyright (C) 2002-2003, 2005-2007, 2009-2016 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
@@ -7,9 +7,24 @@ dnl with or without modifications, as long as this notice is 
preserved.
 
 dnl From Jim Meyering.
 
+AC_DEFUN([gl_TIME_T_IS_SIGNED],
+[
+  AC_CACHE_CHECK([whether time_t is signed],
+    [gl_cv_time_t_is_signed],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM([[#include <time.h>
+                          char time_t_signed[(time_t) -1 < 0 ? 1 : -1];]])],
+       [gl_cv_time_t_is_signed=yes],
+       [gl_cv_time_t_is_signed=no])])
+  if test $gl_cv_time_t_is_signed = yes; then
+    AC_DEFINE([TIME_T_IS_SIGNED], [1], [Define to 1 if time_t is signed.])
+  fi
+])
+
 AC_DEFUN([gl_FUNC_MKTIME],
 [
   AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
+  AC_REQUIRE([gl_TIME_T_IS_SIGNED])
 
   dnl We don't use AC_FUNC_MKTIME any more, because it is no longer maintained
   dnl in Autoconf and because it invokes AC_LIBOBJ.
@@ -169,7 +184,6 @@ main ()
   time_t t, delta;
   int i, j;
   int time_t_signed_magnitude = (time_t) ~ (time_t) 0 < (time_t) -1;
-  int time_t_signed = ! ((time_t) 0 < (time_t) -1);
 
 #if HAVE_DECL_ALARM
   /* This test makes some buggy mktime implementations loop.
@@ -179,11 +193,11 @@ main ()
   alarm (60);
 #endif
 
-  time_t_max = (! time_t_signed
+  time_t_max = (! TIME_T_IS_SIGNED
                 ? (time_t) -1
                 : ((((time_t) 1 << (sizeof (time_t) * CHAR_BIT - 2)) - 1)
                    * 2 + 1));
-  time_t_min = (! time_t_signed
+  time_t_min = (! TIME_T_IS_SIGNED
                 ? (time_t) 0
                 : time_t_signed_magnitude
                 ? ~ (time_t) 0
-- 
2.5.5




reply via email to

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