[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: