Skip to content

Commit 4742526

Browse files
committed
Prefer specified time for vestigial variables
When setting vestigial static variables like tzname, daylight, and timezone, prefer specified timestamps to unspecified ones with abbreviations "-00". Problem reported by Almaz Mingaleev in: https://mm.icann.org/pipermail/tz/2022-May/031438.html * NEWS: Mention this. * localtime.c (may_update_tzname_etc): New function. (settzname): Use it to ignore unspecified timestamps unless they are all we have. Look in reverse order for efficiency.
1 parent 9fa1a53 commit 4742526

File tree

2 files changed

+35
-15
lines changed

2 files changed

+35
-15
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ Unreleased, experimental changes
3030
zic now checks its input for NUL bytes and unterminated lines, and
3131
now supports input line lengths up to 2048 (not 512) bytes.
3232

33+
When tzset and related functions set vestigial static variables
34+
like tzname, they now prefer specified timestamps to unspecified ones.
35+
(Problem reported by Almaz Mingaleev.)
36+
3337

3438
Release 2022a - 2022-03-15 23:02:01 -0700
3539

localtime.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -292,42 +292,58 @@ update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
292292
#endif
293293
}
294294

295+
/* If STDDST_MASK indicates that SP's TYPE provides useful info,
296+
update tzname, timezone, and/or altzone and return STDDST_MASK,
297+
diminished by the provided info if it is a specified local time.
298+
Otherwise, return STDDST_MASK. See settzname for STDDST_MASK. */
299+
static int
300+
may_update_tzname_etc(int stddst_mask, struct state *sp, int type)
301+
{
302+
struct ttinfo *ttisp = &sp->ttis[type];
303+
int this_bit = 1 << ttisp->tt_isdst;
304+
if (stddst_mask & this_bit) {
305+
update_tzname_etc(sp, ttisp);
306+
if (!ttunspecified(sp, type))
307+
return stddst_mask & ~this_bit;
308+
}
309+
return stddst_mask;
310+
}
311+
295312
static void
296313
settzname(void)
297314
{
298315
register struct state * const sp = lclptr;
299316
register int i;
300317

318+
/* If STDDST_MASK & 1 we need info about a standard time.
319+
If STDDST_MASK & 2 we need info about a daylight saving time.
320+
When STDDST_MASK becomes zero we can stop looking. */
321+
int stddst_mask = 0;
322+
301323
#if HAVE_TZNAME
302324
tzname[0] = tzname[1] = (char *) (sp ? wildabbr : gmt);
325+
stddst_mask = 3;
303326
#endif
304327
#if USG_COMPAT
305-
daylight = 0;
306328
timezone = 0;
329+
stddst_mask = 3;
307330
#endif
308331
#if ALTZONE
309332
altzone = 0;
333+
stddst_mask |= 2;
310334
#endif
311-
if (sp == NULL) {
312-
return;
313-
}
314335
/*
315336
** And to get the latest time zone abbreviations into tzname. . .
316337
*/
317-
for (i = 0; i < sp->typecnt; ++i) {
318-
register const struct ttinfo * const ttisp = &sp->ttis[i];
319-
update_tzname_etc(sp, ttisp);
338+
if (sp) {
339+
for (i = sp->timecnt - 1; stddst_mask && 0 <= i; i--)
340+
stddst_mask = may_update_tzname_etc(stddst_mask, sp, sp->types[i]);
341+
for (i = sp->typecnt - 1; stddst_mask && 0 <= i; i--)
342+
stddst_mask = may_update_tzname_etc(stddst_mask, sp, i);
320343
}
321-
for (i = 0; i < sp->timecnt; ++i) {
322-
register const struct ttinfo * const ttisp =
323-
&sp->ttis[
324-
sp->types[i]];
325-
update_tzname_etc(sp, ttisp);
326344
#if USG_COMPAT
327-
if (ttisp->tt_isdst)
328-
daylight = 1;
345+
daylight = stddst_mask >> 1 ^ 1;
329346
#endif
330-
}
331347
}
332348

333349
static void

0 commit comments

Comments
 (0)