1
0
mirror of https://frontier.innolan.net/rainlance/amiga-tz.git synced 2025-11-23 21:43:25 +00:00

Fix some localtime.c problems noted by Christos Zoulas

in: http://mm.icann.org/pipermail/tz/2014-October/021684.html
* localtime.c (tzload): Use ssize_t, not int.  Redo comparison to
avoid the need for an ssize_t value less than -1, which POSIX does
not guarantee.  Use memmove so that we needn't worry about an
ssize_t index.
(tzparse): Remove static always-zero var.  Initialized fields
to zero by hand instead.
(zoneinit): Initialized more fields, to avoid undefined behavior
in tzalloc.
(leapcorr): Fix bug, a stray initialization of a local variable.
* Makefile: Add comment about ssize_t.
* NEWS: Document the above.
This commit is contained in:
Paul Eggert
2014-10-07 21:43:13 -07:00
parent 165f61b401
commit 3bf56b926f
3 changed files with 32 additions and 28 deletions

View File

@ -129,6 +129,7 @@ LDLIBS=
# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
# if you do not want run time warnings about formats that may cause
# year 2000 grief
# -Dssize_t=long on ancient hosts that lack ssize_t
# -DTHREAD_SAFE=1 to make localtime.c thread-safe, as POSIX requires;
# not needed by the main-program tz code, which is single-threaded.
# Append other compiler flags as needed, e.g., -pthread on GNU/Linux.

6
NEWS
View File

@ -26,6 +26,12 @@ 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.
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.)
It also includes some uses of uninitialized variables after tzalloc.
The new code uses the standard type 'ssize_t', which the Makefile
now gives porting advice about.
Release 2014h - 2014-09-25 18:59:03 -0700

View File

@ -200,6 +200,17 @@ int daylight = 0;
long altzone = 0;
#endif /* defined ALTZONE */
/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND. */
static void
init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
{
s->tt_gmtoff = gmtoff;
s->tt_isdst = isdst;
s->tt_abbrind = abbrind;
s->tt_ttisstd = false;
s->tt_ttisgmt = false;
}
static int_fast32_t
detzcode(const char *const codep)
{
@ -304,7 +315,7 @@ tzload(register const char *name, register struct state *const sp,
register int i;
register int fid;
register int stored;
register int nread;
register ssize_t nread;
typedef union {
struct tzhead tzhead;
char buf[2 * sizeof(struct tzhead) +
@ -389,8 +400,9 @@ tzload(register const char *name, register struct state *const sp,
&& (ttisstdcnt == typecnt || ttisstdcnt == 0)
&& (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
goto oops;
if (nread - (p - up->buf)
< (timecnt * stored /* ats */
if (nread
< (p - up->buf /* struct tzhead */
+ timecnt * stored /* ats */
+ timecnt /* types */
+ typecnt * 6 /* ttinfos */
+ charcnt /* chars */
@ -507,8 +519,7 @@ tzload(register const char *name, register struct state *const sp,
if (up->tzhead.tzh_version[0] == '\0')
break;
nread -= p - up->buf;
for (i = 0; i < nread; ++i)
up->buf[i] = p[i];
memmove(up->buf, p, nread);
/*
** If this is a signed narrow time_t system, we're done.
*/
@ -932,7 +943,6 @@ tzparse(const char *name, register struct state *const sp,
int_fast32_t dstoffset;
register char * cp;
register bool load_ok;
static struct ttinfo zttinfo;
stdname = name;
if (lastditch) {
@ -1004,13 +1014,8 @@ tzparse(const char *name, register struct state *const sp,
/*
** Two transitions per year, from EPOCH_YEAR forward.
*/
sp->ttis[0] = sp->ttis[1] = zttinfo;
sp->ttis[0].tt_gmtoff = -dstoffset;
sp->ttis[0].tt_isdst = true;
sp->ttis[0].tt_abbrind = stdlen + 1;
sp->ttis[1].tt_gmtoff = -stdoffset;
sp->ttis[1].tt_isdst = false;
sp->ttis[1].tt_abbrind = 0;
init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
sp->defaulttype = 0;
timecnt = 0;
janfirst = 0;
@ -1129,13 +1134,8 @@ tzparse(const char *name, register struct state *const sp,
/*
** Finally, fill in ttis.
*/
sp->ttis[0] = sp->ttis[1] = zttinfo;
sp->ttis[0].tt_gmtoff = -stdoffset;
sp->ttis[0].tt_isdst = false;
sp->ttis[0].tt_abbrind = 0;
sp->ttis[1].tt_gmtoff = -dstoffset;
sp->ttis[1].tt_isdst = true;
sp->ttis[1].tt_abbrind = stdlen + 1;
init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
sp->typecnt = 2;
sp->defaulttype = 0;
}
@ -1143,10 +1143,7 @@ tzparse(const char *name, register struct state *const sp,
dstlen = 0;
sp->typecnt = 1; /* only standard time */
sp->timecnt = 0;
sp->ttis[0] = zttinfo;
sp->ttis[0].tt_gmtoff = -stdoffset;
sp->ttis[0].tt_isdst = false;
sp->ttis[0].tt_abbrind = 0;
init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
sp->defaulttype = 0;
}
sp->charcnt = stdlen + 1;
@ -1183,10 +1180,11 @@ zoneinit(struct state *sp, char const *name)
sp->leapcnt = 0; /* so, we're off a little */
sp->timecnt = 0;
sp->typecnt = 0;
sp->ttis[0].tt_isdst = 0;
sp->ttis[0].tt_gmtoff = 0;
sp->ttis[0].tt_abbrind = 0;
sp->charcnt = 0;
sp->goback = sp->goahead = false;
init_ttinfo(&sp->ttis[0], 0, false, 0);
strcpy(sp->chars, gmt);
sp->defaulttype = 0;
} else if (! (tzload(name, sp, true)
|| (name && name[0] != ':' && tzparse(name, sp, false))))
return NULL;
@ -2121,7 +2119,6 @@ leapcorr(struct state const *sp, time_t t)
register struct lsinfo const * lp;
register int i;
sp = lclptr;
i = sp->leapcnt;
while (--i >= 0) {
lp = &sp->lsis[i];