diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-04-06 13:03:43 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-04-06 13:03:43 +0000 |
commit | 2bbeb4c0ad49847b1f73ba6281827bf513d05884 (patch) | |
tree | 0d2d7e914ea457f1940519b895053459f0a3689e | |
parent | 727371f88ac06fcb1e5417492f5ab17f5d58d886 (diff) | |
download | ruby-2bbeb4c0ad49847b1f73ba6281827bf513d05884.tar.gz |
* configure.in: test localtime(3) overflow. [ruby-dev:40910]
* time.c (rb_gmtime_r): renamed from rb_gmtime.
(rb_localtime_r): renamed from rb_localtime.
(rb_localtime_r2): call rb_localtime_r and validate the result if
there is overflow problem.
(rb_gmtime_r2): call rb_gmtime_r and validate the result if there
is overflow problem.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27237 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | configure.in | 42 | ||||
-rw-r--r-- | time.c | 59 |
3 files changed, 98 insertions, 14 deletions
@@ -1,3 +1,14 @@ +Tue Apr 6 21:55:25 2010 Tanaka Akira <akr@fsij.org> + + * configure.in: test localtime(3) overflow. [ruby-dev:40910] + + * time.c (rb_gmtime_r): renamed from rb_gmtime. + (rb_localtime_r): renamed from rb_localtime. + (rb_localtime_r2): call rb_localtime_r and validate the result if + there is overflow problem. + (rb_gmtime_r2): call rb_gmtime_r and validate the result if there + is overflow problem. + Tue Apr 6 14:53:17 2010 NAKAMURA Usaku <usa@ruby-lang.org> * include/ruby/win32.h: check definition existance before defining diff --git a/configure.in b/configure.in index 5047e9e054..27fbe56d98 100644 --- a/configure.in +++ b/configure.in @@ -1290,6 +1290,48 @@ if test "$rb_cv_negative_time_t" = yes; then AC_DEFINE(NEGATIVE_TIME_T) fi +# [ruby-dev:40910] overflow of time on FreeBSD +# http://www.freebsd.org/cgi/query-pr.cgi?pr=145341 +AC_CACHE_CHECK(for localtime(3) overflow correctly, rb_cv_localtime_overflow, + [AC_TRY_RUN([ +#include <time.h> + +void +check(time_t t1) +{ + struct tm *tm; + time_t t2; + tm = localtime(&t1); + if (!tm) + return; /* overflow detected. ok. */ + t2 = mktime(tm); + if (t1 == t2) + return; /* round-trip. ok. */ + exit(1); +} + +int +main() +{ + time_t t; + if (~(time_t)0 <= 0) { + t = (((time_t)1) << (sizeof(time_t) * 8 - 2)); + t |= t - 1; + } + else { + t = ~(time_t)0; + } + check(t); + return 0; +} +], + rb_cv_localtime_overflow=yes, + rb_cv_localtime_overflow=no, + rb_cv_localtime_overflow=yes)]) +if test "$rb_cv_localtime_overflow" = no; then + AC_DEFINE(LOCALTIME_OVERFLOW_PROBLEM) +fi + if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then AC_DEFINE(POSIX_SIGNAL) else @@ -840,33 +840,64 @@ static int leap_year_p(long y); #define leap_year_v_p(y) leap_year_p(NUM2LONG(mod(v, INT2FIX(400)))) #ifdef HAVE_GMTIME_R -#define IF_HAVE_GMTIME_R(x) x -#define ASCTIME(tm, buf) asctime_r((tm), (buf)) -#define GMTIME(tm, result) gmtime_r((tm), &(result)) -#define LOCALTIME(tm, result) (tzset(),localtime_r((tm), &(result))) +#define rb_gmtime_r(t, tm) gmtime_r(t, tm) +#define rb_localtime_r(t, tm) localtime_r(t, tm) #else -#define IF_HAVE_GMTIME_R(x) /* nothing */ -#define ASCTIME(tm, buf) asctime(tm) -#define GMTIME(tm, result) rb_gmtime((tm), &(result)) -#define LOCALTIME(tm, result) rb_localtime((tm), &(result)) - static inline struct tm * -rb_gmtime(const time_t *tm, struct tm *result) +rb_gmtime_r(const time_t *tp, struct tm *result) { - struct tm *t = gmtime(tm); + struct tm *t = gmtime(tp); if (t) *result = *t; return t; } static inline struct tm * -rb_localtime(const time_t *tm, struct tm *result) +rb_localtime_r(const time_t *tp, struct tm *result) { - struct tm *t = localtime(tm); + struct tm *t = localtime(tp); if (t) *result = *t; return t; } #endif +static struct tm * +rb_localtime_r2(const time_t *t, struct tm *result) +{ + result = rb_localtime_r(t, result); +#if defined(HAVE_MKTIME) && defined(LOCALTIME_OVERFLOW_PROBLEM) + if (result) { + time_t t2 = mktime(result); + if (*t != t2) + result = NULL; + } +#endif + return result; +} +#define LOCALTIME(tm, result) (tzset(),rb_localtime_r2((tm), &(result))) + +#if !defined(HAVE_STRUCT_TM_TM_GMTOFF) + static struct tm * + rb_gmtime_r2(const time_t *t, struct tm *result) + { + result = rb_gmtime_r(t, result); +#if defined(HAVE_TIMEGM) && defined(LOCALTIME_OVERFLOW_PROBLEM) + if (result) { + time_t t2 = timegm(result); + if (*t != t2) + result = NULL; + } +#endif + return result; + } +# define GMTIME(tm, result) rb_gmtime_r2((tm), &(result)) +#endif + +#ifdef HAVE_GMTIME_R +#define ASCTIME(tm, buf) asctime_r((tm), (buf)) +#else +#define ASCTIME(tm, buf) asctime(tm) +#endif + static const int common_year_yday_offset[] = { -1, -1 + 31, @@ -1085,7 +1116,7 @@ gmtime_with_leapsecond(const time_t *timep, struct tm *result) int sign; int gmtoff_sec, gmtoff_min, gmtoff_hour, gmtoff_day; long gmtoff; - t = localtime_r(timep, result); + t = LOCALTIME(timep, *result); if (t == NULL) return NULL; |