|
|
@@ -501,7 +501,11 @@ char *ctime(const time_t *t)
|
|
|
struct tm xtm;
|
|
|
memset(&xtm, 0, sizeof(xtm));
|
|
|
|
|
|
- return asctime(localtime_r(t, &xtm));
|
|
|
+ if (localtime_r(t, &xtm) == NULL) { /* asctime asserts on NULL. */
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return asctime(&xtm);
|
|
|
}
|
|
|
libc_hidden_def(ctime)
|
|
|
#endif
|
|
|
@@ -512,7 +516,11 @@ char *ctime_r(const time_t *t, char *buf)
|
|
|
{
|
|
|
struct tm xtm;
|
|
|
|
|
|
- return asctime_r(localtime_r(t, &xtm), buf);
|
|
|
+ if (localtime_r(t, &xtm) == NULL) { /* asctime_r asserts on NULL. */
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return asctime_r(&xtm, buf);
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
@@ -561,7 +569,11 @@ struct tm *gmtime(const time_t *timer)
|
|
|
{
|
|
|
register struct tm *ptm = &__time_tm;
|
|
|
|
|
|
- _time_t2tm(timer, 0, ptm); /* Can return NULL... */
|
|
|
+ /* It can return NULL, and then ptm holds a partly written struct;
|
|
|
+ * handing that out as a result loses the error. */
|
|
|
+ if (_time_t2tm(timer, 0, ptm) == NULL) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
|
|
|
return ptm;
|
|
|
}
|
|
|
@@ -586,7 +598,9 @@ struct tm *localtime(const time_t *timer)
|
|
|
|
|
|
/* In this implementation, tzset() is called by localtime_r(). */
|
|
|
|
|
|
- localtime_r(timer, ptm); /* Can return NULL... */
|
|
|
+ if (localtime_r(timer, ptm) == NULL) { /* It can return NULL. */
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
|
|
|
return ptm;
|
|
|
}
|
|
|
@@ -599,15 +613,17 @@ libc_hidden_def(localtime)
|
|
|
struct tm *localtime_r(register const time_t *__restrict timer,
|
|
|
register struct tm *__restrict result)
|
|
|
{
|
|
|
+ struct tm *p;
|
|
|
+
|
|
|
__UCLIBC_MUTEX_LOCK(_time_tzlock);
|
|
|
|
|
|
_time_tzset(*timer < new_rule_starts);
|
|
|
|
|
|
- __time_localtime_tzi(timer, result, _time_tzinfo);
|
|
|
+ p = __time_localtime_tzi(timer, result, _time_tzinfo);
|
|
|
|
|
|
__UCLIBC_MUTEX_UNLOCK(_time_tzlock);
|
|
|
|
|
|
- return result;
|
|
|
+ return p;
|
|
|
}
|
|
|
libc_hidden_def(localtime_r)
|
|
|
|
|
|
@@ -775,7 +791,11 @@ struct tm attribute_hidden *__time_localtime_tzi(register const time_t *__restri
|
|
|
}
|
|
|
*x = *timer + offset;
|
|
|
|
|
|
- _time_t2tm(x, days, result);
|
|
|
+ /* Out of range for a struct tm; tm_isdst below would read a
|
|
|
+ * result that was never written. */
|
|
|
+ if (_time_t2tm(x, days, result) == NULL) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
result->tm_isdst = dst;
|
|
|
#ifdef __UCLIBC_HAS_TM_EXTENSIONS__
|
|
|
# ifdef __USE_BSD
|
|
|
@@ -1725,7 +1745,9 @@ LOOP:
|
|
|
buf = o;
|
|
|
|
|
|
if (!code) { /* s */
|
|
|
- localtime_r(&t, tm); /* TODO: check for failure? */
|
|
|
+ if (localtime_r(&t, tm) == NULL) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
i = 0;
|
|
|
do { /* Now copy values from tm to fields. */
|
|
|
fields[i] = ((int *) tm)[i];
|
|
|
@@ -2306,19 +2328,29 @@ struct tm attribute_hidden *_time_t2tm(const time_t *__restrict timer,
|
|
|
vp = _vals;
|
|
|
do {
|
|
|
if ((v = *vp) == 7) {
|
|
|
- /* Overflow checking, assuming time_t is long int... */
|
|
|
-#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L)
|
|
|
-#if (INT_MAX == 2147483647L) && (LONG_MAX == 9223372036854775807L)
|
|
|
- /* Valid range for t is [-784223472856L, 784223421720L].
|
|
|
- * Outside of this range, the tm_year field will overflow. */
|
|
|
- if (((unsigned long)(t + offset- -784223472856L))
|
|
|
- > (784223421720L - -784223472856L)
|
|
|
+ /* t counts days here, and tm_year is an int, so the
|
|
|
+ * broken-down time only exists while t stays inside
|
|
|
+ * [-784223472856, 784223421720] -- those bounds are
|
|
|
+ * INT_MAX years either side of the epoch.
|
|
|
+ *
|
|
|
+ * This used to ask whether long was wider than int,
|
|
|
+ * which is false on the 32-bit targets that set
|
|
|
+ * UCLIBC_USE_TIME64: the check was compiled out on
|
|
|
+ * exactly the configurations that need it. Ask about
|
|
|
+ * time_t instead. sizeof is a constant, so a 32-bit
|
|
|
+ * time_t -- whose days can never leave the range --
|
|
|
+ * still compiles the test away. */
|
|
|
+#if INT_MAX == 2147483647
|
|
|
+ if ((sizeof(time_t) > 4)
|
|
|
+ && (((uintmax_t)((intmax_t) t + offset
|
|
|
+ - (intmax_t) -784223472856LL))
|
|
|
+ > (uintmax_t)(784223421720LL - -784223472856LL))
|
|
|
) {
|
|
|
+ __set_errno(EOVERFLOW);
|
|
|
return NULL;
|
|
|
}
|
|
|
#else
|
|
|
-#error overflow conditions unknown
|
|
|
-#endif
|
|
|
+#error tm_year range unknown for this int width
|
|
|
#endif
|
|
|
|
|
|
/* We have days since the epoch, so caluclate the weekday. */
|
|
|
@@ -2554,7 +2586,10 @@ DST_CORRECT:
|
|
|
d = ((struct tm *)p)->tm_isdst;
|
|
|
t = secs;
|
|
|
|
|
|
- __time_localtime_tzi(&t, (struct tm *)p, tzi);
|
|
|
+ if (__time_localtime_tzi(&t, (struct tm *)p, tzi) == NULL) {
|
|
|
+ t = ((time_t)(-1));
|
|
|
+ goto DONE;
|
|
|
+ }
|
|
|
|
|
|
if (t == ((time_t)(-1))) { /* Remember, time_t can be unsigned. */
|
|
|
goto DONE;
|