Bug#1057856: glibc: mktime now returns clock for UTC with isdst=1
Package: libc6
Version: 2.36-9+deb12u3
Severity: normal
Tags: upstream
X-Debbugs-Cc: paulo.tome@gmail.com
Dear Maintainer,
*** Reporter, please consider answering these questions, where appropriate ***
* What led up to the situation?
* What exactly did you do (or not do) that was effective (or
ineffective)?
* What was the outcome of this action?
* What outcome did you expect instead?
*** End of the template - remove these template lines ***
After compiling Erlang from source (erlang.org) a test case failed. The
test case detects if local time is converted correctly to universal time
even if isdst=1 for the UTC timezone. The following issue reports the
details: https://github.com/erlang/otp/issues/7938
I created a small test program that reproduces the behavior. The program
calls mktime for a certain date, with isdst=1 in the tm struct.
When setting TZ=UTC in the environment, mktime returns a valid clock
offset by one hour. In previous versions of glibc (tested 2.35 on Ubuntu
LTS 22.04.3) the same call to mktime returns -1. The error (-1) makes
sense, since the UTC timezone does not have DST.
After downloading the Debian glibc-source for 2.36, I see a patch that
could explain this behavior.
/usr/src/glibc/debian/patches/git-updates.diff
+ /* No unusual DST offset was found nearby. Assume one-hour DST. */
+ t += 60 * 60 * dst_difference;
+ if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
+ goto offset_found;
+
__set_errno (EOVERFLOW);
return -1;
}
This change was not present on the other glibc I tested (2.35 on
Ubuntu). I checked upstream glibc 2.38 and the change is in the source.
I'm not sure if this is a bug, but for the UTC timezone I would expect
an error if we asked for the time with DST.
For reference, this is the test program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(int argc, char *argv[])
{
int check_dst;
/* Check DST given as input */
if (argc == 2) {
check_dst = atoi(argv[1]);
} else {
printf("./check_dst <isdst value>\n");
exit(EXIT_FAILURE);
}
struct tm t;
t.tm_year = 2008 - 1900;
t.tm_mon = 8 - 1;
t.tm_mday = 1;
t.tm_hour = 0;
t.tm_min = 0;
t.tm_sec = 0;
t.tm_isdst = check_dst;
time_t clock = mktime(&t);
printf("tzname[0]: %s, tzname[1]: %s\n", tzname[0], tzname[1]);
printf("\tdst before: %d\n\tdst after: %d\n", check_dst, t.tm_isdst);
printf("\tclock: %ld\n", clock);
exit(EXIT_SUCCESS);
}
And the output:
$ gcc -o check_dst check_dst.c
$ TZ=UTC ./check_dst 0
tzname[0]: UTC, tzname[1]: UTC
dst before: 0
dst after: 0
clock: 1217548800
$ TZ=UTC ./check_dst 1
tzname[0]: UTC, tzname[1]: UTC
dst before: 1
dst after: 0
clock: 1217545200
-- System Information:
Debian Release: 12.2
APT prefers stable-updates
APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)
Kernel: Linux 6.1.0-13-amd64 (SMP w/4 CPU threads; PREEMPT)
Kernel taint flags: TAINT_FIRMWARE_WORKAROUND
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages libc6 depends on:
ii libgcc-s1 12.2.0-14
Versions of packages libc6 recommends:
ii libidn2-0 2.3.3-1+b1
Versions of packages libc6 suggests:
ii debconf [debconf-2.0] 1.5.82
pn glibc-doc <none>
ii libc-l10n 2.36-9+deb12u3
pn libnss-nis <none>
pn libnss-nisplus <none>
ii locales 2.36-9+deb12u3
-- debconf information:
glibc/upgrade: true
glibc/disable-screensaver:
glibc/kernel-too-old:
glibc/restart-services:
libraries/restart-without-asking: false
glibc/kernel-not-supported:
glibc/restart-failed:
Reply to: