[前][次][番号順一覧][スレッド一覧]

ruby-changes:15347

From: akr <ko1@a...>
Date: Tue, 6 Apr 2010 22:04:04 +0900 (JST)
Subject: [ruby-changes:15347] Ruby:r27237 (trunk): * configure.in: test localtime(3) overflow.

akr	2010-04-06 22:03:43 +0900 (Tue, 06 Apr 2010)

  New Revision: 27237

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=27237

  Log:
    * 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.

  Modified files:
    trunk/ChangeLog
    trunk/configure.in
    trunk/time.c

Index: time.c
===================================================================
--- time.c	(revision 27236)
+++ time.c	(revision 27237)
@@ -840,33 +840,64 @@
 #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 @@
     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;
 
Index: configure.in
===================================================================
--- configure.in	(revision 27236)
+++ configure.in	(revision 27237)
@@ -1290,6 +1290,48 @@
   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
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 27236)
+++ ChangeLog	(revision 27237)
@@ -1,3 +1,14 @@
+Tue Apr  6 21:55:25 2010  Tanaka Akira  <akr@f...>
+
+	* 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@r...>
 
 	* include/ruby/win32.h: check definition existance before defining

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]