diff options
Diffstat (limited to 'localtime.c')
-rw-r--r-- | localtime.c | 91 |
1 files changed, 17 insertions, 74 deletions
diff --git a/localtime.c b/localtime.c index 940a04fd09ab..7ae9ce5e519d 100644 --- a/localtime.c +++ b/localtime.c @@ -106,7 +106,7 @@ static char const UNSPEC[] = "-00"; for ttunspecified to work without crashing. */ enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 }; -/* Limit to time zone abbreviation length in POSIX.1-2017-style TZ strings. +/* Limit to time zone abbreviation length in proleptic TZ strings. This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */ #ifndef TZNAME_MAXIMUM # define TZNAME_MAXIMUM 255 @@ -130,11 +130,6 @@ struct state { char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"), 2 * (TZNAME_MAXIMUM + 1))]; struct lsinfo lsis[TZ_MAX_LEAPS]; - - /* The time type to use for early times or if no transitions. - It is always zero for recent tzdb releases. - It might be nonzero for data from tzdb 2018e or earlier. */ - int defaulttype; }; enum r_type { @@ -187,8 +182,9 @@ static int lcl_is_set; ** objects: a broken-down time structure and an array of char. ** Thanks to Paul Eggert for noting this. ** -** This requirement was removed in C99, so support it only if requested, -** as support is more likely to lead to bugs in badly written programs. +** Although this requirement was removed in C99 it is still present in POSIX. +** Follow the requirement if SUPPORT_C89, even though this is more likely to +** trigger latent bugs in programs. */ #if SUPPORT_C89 @@ -710,58 +706,6 @@ tzloadbody(char const *name, struct state *sp, bool doextend, if (sp->typecnt == 0) return EINVAL; - /* Infer sp->defaulttype from the data. Although this default - type is always zero for data from recent tzdb releases, - things are trickier for data from tzdb 2018e or earlier. - - The first set of heuristics work around bugs in 32-bit data - generated by tzdb 2013c or earlier. The workaround is for - zones like Australia/Macquarie where timestamps before the - first transition have a time type that is not the earliest - standard-time type. See: - https://mm.icann.org/pipermail/tz/2013-May/019368.html */ - /* - ** If type 0 does not specify local time, or is unused in transitions, - ** it's the type to use for early times. - */ - for (i = 0; i < sp->timecnt; ++i) - if (sp->types[i] == 0) - break; - i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0; - /* - ** Absent the above, - ** if there are transition times - ** and the first transition is to a daylight time - ** find the standard type less than and closest to - ** the type of the first transition. - */ - if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) { - i = sp->types[0]; - while (--i >= 0) - if (!sp->ttis[i].tt_isdst) - break; - } - /* The next heuristics are for data generated by tzdb 2018e or - earlier, for zones like EST5EDT where the first transition - is to DST. */ - /* - ** If no result yet, find the first standard type. - ** If there is none, punt to type zero. - */ - if (i < 0) { - i = 0; - while (sp->ttis[i].tt_isdst) - if (++i >= sp->typecnt) { - i = 0; - break; - } - } - /* A simple 'sp->defaulttype = 0;' would suffice here if we - didn't have to worry about 2018e-or-earlier data. Even - simpler would be to remove the defaulttype member and just - use 0 in its place. */ - sp->defaulttype = i; - return 0; } @@ -807,7 +751,7 @@ is_digit(char c) ** Return a pointer to that character. */ -ATTRIBUTE_REPRODUCIBLE static const char * +ATTRIBUTE_PURE_114833 static const char * getzname(register const char *strp) { register char c; @@ -828,7 +772,7 @@ getzname(register const char *strp) ** We don't do any checking here; checking is done later in common-case code. */ -ATTRIBUTE_REPRODUCIBLE static const char * +ATTRIBUTE_PURE_114833 static const char * getqzname(register const char *strp, const int delim) { register int c; @@ -1080,7 +1024,7 @@ transtime(const int year, register const struct rule *const rulep, } /* -** Given a POSIX.1-2017-style TZ string, fill in the rule tables as +** Given a POSIX.1 proleptic TZ string, fill in the rule tables as ** appropriate. */ @@ -1183,11 +1127,13 @@ tzparse(const char *name, struct state *sp, struct state const *basep) do { int_fast32_t yearsecs = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY; + time_t janfirst1 = janfirst; yearbeg--; - if (increment_overflow_time(&janfirst, -yearsecs)) { + if (increment_overflow_time(&janfirst1, -yearsecs)) { janoffset = -yearsecs; break; } + janfirst = janfirst1; } while (atlo < janfirst && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg); @@ -1313,7 +1259,7 @@ tzparse(const char *name, struct state *sp, struct state const *basep) /* ** Transitions from DST to DDST ** will effectively disappear since - ** POSIX.1-2017 provides for only one + ** proleptic TZ strings have only one ** DST offset. */ if (isdst && !sp->ttis[j].tt_ttisstd) { @@ -1342,7 +1288,6 @@ tzparse(const char *name, struct state *sp, struct state const *basep) sp->timecnt = 0; init_ttinfo(&sp->ttis[0], -stdoffset, false, 0); } - sp->defaulttype = 0; sp->charcnt = charcnt; cp = sp->chars; memcpy(cp, stdname, stdlen); @@ -1378,7 +1323,6 @@ zoneinit(struct state *sp, char const *name) sp->goback = sp->goahead = false; init_ttinfo(&sp->ttis[0], 0, false, 0); strcpy(sp->chars, utc); - sp->defaulttype = 0; return 0; } else { int err = tzload(name, sp, true); @@ -1465,8 +1409,8 @@ tzfree(timezone_t sp) } /* -** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and -** ctime_r are obsolescent and have potential security problems that +** NetBSD 6.1.4 has ctime_rz, but omit it because C23 deprecates ctime and +** POSIX.1-2024 removes ctime_r. Both have potential security problems that ** ctime_rz would share. Callers can instead use localtime_rz + strftime. ** ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work @@ -1484,8 +1428,7 @@ tzfree(timezone_t sp) ** ** If successful and SETNAME is nonzero, ** set the applicable parts of tzname, timezone and altzone; -** however, it's OK to omit this step -** if the timezone is compatible with POSIX.1-2017 +** however, it's OK to omit this step for proleptic TZ strings ** since in that case tzset should have already done this step correctly. ** SETNAME's type is int_fast32_t for compatibility with gmtsub, ** but it is actually a boolean and its value should be 0 or 1. @@ -1553,7 +1496,7 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t setname, return result; } if (sp->timecnt == 0 || t < sp->ats[0]) { - i = sp->defaulttype; + i = 0; } else { register int lo = 1; register int hi = sp->timecnt; @@ -2285,7 +2228,7 @@ mktime(struct tm *tmp) } #if STD_INSPIRED -/* This function is obsolescent and may disapper in future releases. +/* This function is obsolescent and may disappear in future releases. Callers can instead use mktime. */ time_t timelocal(struct tm *tmp) @@ -2303,7 +2246,7 @@ timelocal(struct tm *tmp) # define EXTERN_TIMEOFF static #endif -/* This function is obsolescent and may disapper in future releases. +/* This function is obsolescent and may disappear in future releases. Callers can instead use mktime_z with a fixed-offset zone. */ EXTERN_TIMEOFF time_t timeoff(struct tm *tmp, long offset) |