[tz] [PROPOSED 2/3] Don’t reject all TZif files with zero typecnt

Paul Eggert eggert at cs.ucla.edu
Tue Jun 5 00:28:32 UTC 2018


* 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



More information about the tz mailing list