* 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