mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
727371f88a
commit
2bbeb4c0ad
3 changed files with 108 additions and 24 deletions
11
ChangeLog
11
ChangeLog
|
@ -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
|
||||
|
|
42
configure.in
42
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
|
||||
|
|
79
time.c
79
time.c
|
@ -840,31 +840,62 @@ 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
|
||||
static inline struct tm *
|
||||
rb_gmtime_r(const time_t *tp, struct tm *result)
|
||||
{
|
||||
struct tm *t = gmtime(tp);
|
||||
if (t) *result = *t;
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline struct tm *
|
||||
rb_localtime_r(const time_t *tp, struct tm *result)
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
struct tm *t = gmtime(tm);
|
||||
if (t) *result = *t;
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline struct tm *
|
||||
rb_localtime(const time_t *tm, struct tm *result)
|
||||
{
|
||||
struct tm *t = localtime(tm);
|
||||
if (t) *result = *t;
|
||||
return t;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const int common_year_yday_offset[] = {
|
||||
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue