[PROPOSED] Increase TZ_MAX_CHARS from 50 to 256
With the current localtime.c implementation, increasing TZ_MAX_CHARS from 50 to its maximum value 256 does not allocate more memory, so there is little point to the limit of 50. * NEWS, localtime.c: Mention this. * tzfile.h (TZ_MAX_CHARS): Increase from 50 to 256. * zic.c (writezone): If -v, warn about going over the old limit. --- NEWS | 7 +++++++ localtime.c | 4 ++-- tzfile.h | 6 +++--- zic.c | 5 +++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 95b1851c..dd592871 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ Unreleased, experimental changes Briefly: The "right" TZif files are no longer installed by default. -DTZ_RUNTIME_LEAPS=0 disables runtime support for leap seconds. + TZif files are no longer limited to 50 bytes of abbreviations. Several integer overflow bugs have been fixed. Changes to build procedure @@ -29,6 +30,12 @@ Unreleased, experimental changes POSIX, shrinks tzcode's attack surface, and is more efficient, it fails to support Internet RFC 9636's leap seconds. + zic now can generate, and localtime.c can now use, TZif files that + hold up to 256 bytes of abbreviations, counting trailing NULs. + The previous limit was 50 bytes, and some tzdata TZif files were + already consuming 40 bytes. zic -v warns if it generates a file + that exceeds the old 50-byte limit. + localtime.c no longer accesses the posixrules file generated by zic -p. Hence for obsolete and nonconforming settings like TZ="AST4ADT" it now typically falls back on US DST rules, rather diff --git a/localtime.c b/localtime.c index ed7a32f2..32835d08 100644 --- a/localtime.c +++ b/localtime.c @@ -1227,8 +1227,8 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags, if (tzparse(&up->buf[1], ts, sp)) { /* Attempt to reuse existing abbreviations. - Without this, America/Anchorage would be right on - the edge after 2037 when TZ_MAX_CHARS is 50, as + Without this, America/Anchorage would + consume 50 bytes for abbreviations, as sp->charcnt equals 40 (for LMT AST AWT APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for AKST AKDT). Reusing means sp->charcnt can diff --git a/tzfile.h b/tzfile.h index 71b60f37..1b1bac4a 100644 --- a/tzfile.h +++ b/tzfile.h @@ -95,13 +95,13 @@ struct tzhead { #ifndef TZ_MAX_TYPES /* This must be at least 18 for Europe/Vilnius with 'zic -b fat'. */ -# define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ +# define TZ_MAX_TYPES 256 /* Limited to 256 by Internet RFC 9636. */ #endif /* !defined TZ_MAX_TYPES */ #ifndef TZ_MAX_CHARS /* This must be at least 40 for America/Anchorage. */ -# define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ +# define TZ_MAX_CHARS 256 /* Maximum number of abbreviation characters */ + /* (limited to 256 by Internet RFC 9636) */ #endif /* !defined TZ_MAX_CHARS */ #ifndef TZ_MAX_LEAPS diff --git a/zic.c b/zic.c index 73155138..1a2f4741 100644 --- a/zic.c +++ b/zic.c @@ -2986,6 +2986,11 @@ writezone(const char *const name, const char *const string, char version, continue; } + if (pass == 2 && noise && 50 < thischarcnt) + warning(_("%s: pre-2026 reference clients mishandle" + " more than 50 bytes of abbreviations"), + name); + /* Output a LO_TIME transition if needed; see limitrange. But do not go below the minimum representable value for this pass. */ -- 2.51.0
participants (1)
-
Paul Eggert