summaryrefslogtreecommitdiff
path: root/time.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-04-06 13:03:43 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-04-06 13:03:43 +0000
commit2bbeb4c0ad49847b1f73ba6281827bf513d05884 (patch)
tree0d2d7e914ea457f1940519b895053459f0a3689e /time.c
parent727371f88ac06fcb1e5417492f5ab17f5d58d886 (diff)
* 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
Diffstat (limited to 'time.c')
-rw-r--r--time.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/time.c b/time.c
index d43165ec55..08d4199fdb 100644
--- a/time.c
+++ b/time.c
@@ -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;