aboutsummaryrefslogtreecommitdiff
path: root/time
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2023-01-05 18:21:25 +0100
committerFlorian Weimer <fweimer@redhat.com>2023-01-05 18:22:55 +0100
commit35141f304e319109c322f797ae71c0b9420ccb05 (patch)
treed0b3dc256825087141dd07824a98a224a58ef420 /time
parent8f27dc1af5238adbc14000f073178ee4a2c2b3cf (diff)
downloadglibc-35141f304e319109c322f797ae71c0b9420ccb05.zip
glibc-35141f304e319109c322f797ae71c0b9420ccb05.tar.gz
glibc-35141f304e319109c322f797ae71c0b9420ccb05.tar.bz2
time: Set daylight to 1 for matching DST/offset change (bug 29951)
The daylight variable is supposed to be set to 1 if DST is ever in use for the current time zone. But __tzfile_read used to do this: __daylight = rule_stdoff != rule_dstoff; This check can fail to set __daylight to 1 if the DST and non-DST offsets happen to be the same.
Diffstat (limited to 'time')
-rw-r--r--time/tzfile.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/time/tzfile.c b/time/tzfile.c
index 394b098..8bba4e5 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -61,6 +61,10 @@ static size_t num_leaps;
static struct leap *leaps;
static char *tzspec;
+/* Used to restore the daylight variable during time conversion, as if
+ tzset had been called. */
+static int daylight_saved;
+
#include <endian.h>
#include <byteswap.h>
@@ -438,36 +442,35 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
if (__tzname[1] == NULL)
__tzname[1] = __tzname[0];
+ daylight_saved = 0;
if (num_transitions == 0)
/* Use the first rule (which should also be the only one). */
rule_stdoff = rule_dstoff = types[0].offset;
else
{
- int stdoff_set = 0, dstoff_set = 0;
- rule_stdoff = rule_dstoff = 0;
+ rule_stdoff = 0;
+
+ /* Search for the last rule with a standard time offset. This
+ will be used for the global timezone variable. */
i = num_transitions - 1;
do
- {
- if (!stdoff_set && !types[type_idxs[i]].isdst)
- {
- stdoff_set = 1;
- rule_stdoff = types[type_idxs[i]].offset;
- }
- else if (!dstoff_set && types[type_idxs[i]].isdst)
- {
- dstoff_set = 1;
- rule_dstoff = types[type_idxs[i]].offset;
- }
- if (stdoff_set && dstoff_set)
+ if (!types[type_idxs[i]].isdst)
+ {
+ rule_stdoff = types[type_idxs[i]].offset;
break;
- }
+ }
+ else
+ daylight_saved = 1;
while (i-- > 0);
- if (!dstoff_set)
- rule_dstoff = rule_stdoff;
+ /* Keep searching to see if there is a DST rule. This
+ information will be used to set the global daylight
+ variable. */
+ while (i-- > 0 && !daylight_saved)
+ daylight_saved = types[type_idxs[i]].isdst;
}
- __daylight = rule_stdoff != rule_dstoff;
+ __daylight = daylight_saved;
__timezone = -rule_stdoff;
done:
@@ -731,7 +734,7 @@ __tzfile_compute (__time64_t timer, int use_localtime,
}
struct ttinfo *info = &types[i];
- __daylight = rule_stdoff != rule_dstoff;
+ __daylight = daylight_saved;
__timezone = -rule_stdoff;
if (__tzname[0] == NULL)