mirror of
https://frontier.innolan.net/rainlance/amiga-tz.git
synced 2026-05-06 18:19:05 +00:00
Fix EOVERFLOW-related problems noted by Chistos Zoulas.
See: http://mm.icann.org/pipermail/tz/2014-October/021692.html * asctime.c (asctime_r): Remove now-unnecessary EOVERFLOW ifdef. * localtime.c (timesub): Set errno to EOVERFLOW on overflow. POSIX requires this. (ctime, ctime_r): Return NULL instead of having undefined behavior when the time stamp is out of struct tm range. NetBSD does this, the standards allow it, and it's nicer for users. * private.h (EOVERFLOW): Default to EINVAL on ancient hosts that lack it. * NEWS: Document this.
This commit is contained in:
5
NEWS
5
NEWS
@@ -26,6 +26,11 @@ Unreleased, experimental changes
|
||||
This change is a companion to the tzname change in 2014h, and is
|
||||
designed to make timezone and altzone more compatible with tzname.
|
||||
|
||||
The tz library's functions now set errno to EOVERFLOW if they fail
|
||||
because the result cannot be represented. ctime and ctime_r now
|
||||
return NULL and set errno when a time stamp is out of range, rather
|
||||
than having undefined behavior.
|
||||
|
||||
Some bugs associated with the new 2014g functions have been fixed.
|
||||
This includes a bug that largely incapacitated the new functions
|
||||
time2posix_z and posix2time_z. (Thanks to Christos Zoulas.)
|
||||
|
||||
@@ -112,11 +112,7 @@ asctime_r(register const struct tm *timeptr, char *buf)
|
||||
if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime)
|
||||
return strcpy(buf, result);
|
||||
else {
|
||||
#ifdef EOVERFLOW
|
||||
errno = EOVERFLOW;
|
||||
#else /* !defined EOVERFLOW */
|
||||
errno = EINVAL;
|
||||
#endif /* !defined EOVERFLOW */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
23
localtime.c
23
localtime.c
@@ -1541,13 +1541,13 @@ timesub(const time_t *const timep, const int_fast32_t offset,
|
||||
tdelta = tdays / DAYSPERLYEAR;
|
||||
if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
|
||||
&& tdelta <= INT_MAX))
|
||||
return NULL;
|
||||
goto out_of_range;
|
||||
idelta = tdelta;
|
||||
if (idelta == 0)
|
||||
idelta = (tdays < 0) ? -1 : 1;
|
||||
newy = y;
|
||||
if (increment_overflow(&newy, idelta))
|
||||
return NULL;
|
||||
goto out_of_range;
|
||||
leapdays = leaps_thru_end_of(newy - 1) -
|
||||
leaps_thru_end_of(y - 1);
|
||||
tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
|
||||
@@ -1576,17 +1576,17 @@ timesub(const time_t *const timep, const int_fast32_t offset,
|
||||
}
|
||||
while (idays < 0) {
|
||||
if (increment_overflow(&y, -1))
|
||||
return NULL;
|
||||
goto out_of_range;
|
||||
idays += year_lengths[isleap(y)];
|
||||
}
|
||||
while (idays >= year_lengths[isleap(y)]) {
|
||||
idays -= year_lengths[isleap(y)];
|
||||
if (increment_overflow(&y, 1))
|
||||
return NULL;
|
||||
goto out_of_range;
|
||||
}
|
||||
tmp->tm_year = y;
|
||||
if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
|
||||
return NULL;
|
||||
goto out_of_range;
|
||||
tmp->tm_yday = idays;
|
||||
/*
|
||||
** The "extra" mods below avoid overflow problems.
|
||||
@@ -1617,6 +1617,10 @@ timesub(const time_t *const timep, const int_fast32_t offset,
|
||||
tmp->TM_GMTOFF = offset;
|
||||
#endif /* defined TM_GMTOFF */
|
||||
return tmp;
|
||||
|
||||
out_of_range:
|
||||
errno = EOVERFLOW;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -1628,15 +1632,16 @@ ctime(const time_t *const timep)
|
||||
** to local time in the form of a string. It is equivalent to
|
||||
** asctime(localtime(timer))
|
||||
*/
|
||||
return asctime(localtime(timep));
|
||||
struct tm *tmp = localtime(timep);
|
||||
return tmp ? asctime(tmp) : NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
ctime_r(const time_t *const timep, char *buf)
|
||||
{
|
||||
struct tm mytm;
|
||||
|
||||
return asctime_r(localtime_r(timep, &mytm), buf);
|
||||
struct tm mytm;
|
||||
struct tm *tmp = localtime_r(timep, &mytm);
|
||||
return tmp ? asctime_r(tmp, buf) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -101,11 +101,16 @@
|
||||
|
||||
#include "sys/types.h" /* for time_t */
|
||||
#include "stdio.h"
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
#include "limits.h" /* for CHAR_BIT et al. */
|
||||
#include "stdlib.h"
|
||||
|
||||
#include "errno.h"
|
||||
|
||||
#ifndef EOVERFLOW
|
||||
# define EOVERFLOW EINVAL
|
||||
#endif
|
||||
|
||||
#if HAVE_GETTEXT
|
||||
#include "libintl.h"
|
||||
#endif /* HAVE_GETTEXT */
|
||||
|
||||
Reference in New Issue
Block a user