aboutsummaryrefslogtreecommitdiff
path: root/localtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'localtime.c')
-rw-r--r--localtime.c91
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)