[PROPOSED 1/3] Don’t reject TZif TZ strings that lack DST
* NEWS: Mention this. * localtime.c (tzloadbody): Don’t require a TZif file’s POSIX TZ string to specify DST. That way, the TZ string consistently overrides the type of the TZif file’s last transition, instead of overriding only when specifying DST. Although this currently matters only for invalid TZif files where the TZ string disagrees with the last transition’s time type, it will become more important if we stop requiring at least one time type in the binary data, as the TZ string will then be the only source for time types. --- NEWS | 6 ++++++ localtime.c | 11 +++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index ce009e7..2e9bf99 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,12 @@ Unreleased, experimental changes legacy zones EST5EDT, CST6CDT, MST7MDT, PST8PDT, CET, MET, and EET, which previously used nonzero types for these timestamps. + localtime.c no longer ignores TZif POSIX-style TZ strings that + specify only standard time. Instead, these TZ strings now + override the default time type for timestamps after the last + transition (or for all time stamps if there are no transitions), + just as DST strings specifying DST have always done. + Changes to documentation New restrictions: A Rule name must start with a character that diff --git a/localtime.c b/localtime.c index 21160c0..5a3fe91 100644 --- a/localtime.c +++ b/localtime.c @@ -587,8 +587,7 @@ tzloadbody(char const *name, struct state *sp, bool doextend, struct state *ts = &lsp->u.st; up->buf[nread - 1] = '\0'; - if (tzparse(&up->buf[1], ts, false) - && ts->typecnt == 2) { + if (tzparse(&up->buf[1], ts, false)) { /* Attempt to reuse existing abbreviations. Without this, America/Anchorage would be right on @@ -599,7 +598,7 @@ tzloadbody(char const *name, struct state *sp, bool doextend, stay 40 in this example. */ int gotabbr = 0; int charcnt = sp->charcnt; - for (i = 0; i < 2; i++) { + for (i = 0; i < ts->typecnt; i++) { char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind; int j; for (j = 0; j < charcnt; j++) @@ -618,7 +617,7 @@ tzloadbody(char const *name, struct state *sp, bool doextend, } } } - if (gotabbr == 2) { + if (gotabbr == ts->typecnt) { sp->charcnt = charcnt; /* Ignore any trailing, no-op transitions generated @@ -640,8 +639,8 @@ tzloadbody(char const *name, struct state *sp, bool doextend, sp->timecnt++; i++; } - sp->ttis[sp->typecnt++] = ts->ttis[0]; - sp->ttis[sp->typecnt++] = ts->ttis[1]; + for (i = 0; i < ts->typecnt; i++) + sp->ttis[sp->typecnt++] = ts->ttis[i]; } } } -- 2.17.1
* NEWS: Mention this. * localtime.c (tzloadbody): Check for zero typecnt after resolving POSIX-like TZ string, not before. --- NEWS | 6 ++++++ localtime.c | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 2e9bf99..01873ab 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,12 @@ Unreleased, experimental changes legacy zones EST5EDT, CST6CDT, MST7MDT, PST8PDT, CET, MET, and EET, which previously used nonzero types for these timestamps. + localtime.c no longer requires at least one time type in TZif + files that lack transitions or have a POSIX-style TZ string. This + future-proofs the code against possible future extensions to the + format that would allow TZif files with POSIX-style TZ strings and + without transitions or time types. + localtime.c no longer ignores TZif POSIX-style TZ strings that specify only standard time. Instead, these TZ strings now override the default time type for timestamps after the last diff --git a/localtime.c b/localtime.c index 5a3fe91..9c31642 100644 --- a/localtime.c +++ b/localtime.c @@ -450,8 +450,11 @@ tzloadbody(char const *name, struct state *sp, bool doextend, int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt); int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt); char const *p = up->buf + tzheadsize; + /* Although tzfile(5) currently requires typecnt to be nonzero, + support future formats that may allow zero typecnt + in files that have a TZ string and no transitions. */ if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS - && 0 < typecnt && typecnt < TZ_MAX_TYPES + && 0 <= typecnt && typecnt < TZ_MAX_TYPES && 0 <= timecnt && timecnt < TZ_MAX_TIMES && 0 <= charcnt && charcnt < TZ_MAX_CHARS && (ttisstdcnt == typecnt || ttisstdcnt == 0) @@ -644,6 +647,8 @@ tzloadbody(char const *name, struct state *sp, bool doextend, } } } + if (sp->typecnt == 0) + return EINVAL; if (sp->timecnt > 1) { for (i = 1; i < sp->timecnt; ++i) if (typesequiv(sp, sp->types[i], sp->types[0]) && -- 2.17.1
* NEWS: Mention this. * localtime.c (tzloadbody): Avoid subscript error if timecnt is zero, which tzfile(5) allows. --- NEWS | 4 ++++ localtime.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 01873ab..34f7810 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,10 @@ Unreleased, experimental changes format that would allow TZif files with POSIX-style TZ strings and without transitions or time types. + A read-access subscript error in localtime.c has been fixed. + It could occur only in TZif files with timecnt == 0, something that + does not happen in practice now but could happen in future versions. + localtime.c no longer ignores TZif POSIX-style TZ strings that specify only standard time. Instead, these TZ strings now override the default time type for timestamps after the last diff --git a/localtime.c b/localtime.c index 9c31642..f205363 100644 --- a/localtime.c +++ b/localtime.c @@ -632,7 +632,8 @@ tzloadbody(char const *name, struct state *sp, bool doextend, sp->timecnt--; for (i = 0; i < ts->timecnt; i++) - if (sp->ats[sp->timecnt - 1] < ts->ats[i]) + if (sp->timecnt == 0 + || sp->ats[sp->timecnt - 1] < ts->ats[i]) break; while (i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES) { -- 2.17.1
participants (1)
-
Paul Eggert