* 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:
akr 2010-04-06 13:03:43 +00:00
Родитель 727371f88a
Коммит 2bbeb4c0ad
3 изменённых файлов: 108 добавлений и 24 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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
Просмотреть файл

@ -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;