mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@libc.org>
To: Alexander Weps <exander77@pm.me>
Cc: musl@lists.openwall.com
Subject: Re: [musl] Broken mktime calculations when crossing DST boundary
Date: Mon, 25 Mar 2024 08:21:13 -0400	[thread overview]
Message-ID: <20240325122113.GB4163@brightrain.aerifal.cx> (raw)
In-Reply-To: <RRefgIKYIkNjPM9zuJIzVCjZBi0GC5MnqEYNyLq9Pi2ZquzfwVb6CJSEjDZEd2jMgR0nmf_hoJd4Zl-iMQHW-Qc5K3x9vwt3oskinb1MC58=@pm.me>

On Mon, Mar 25, 2024 at 11:52:00AM +0000, Alexander Weps wrote:
> This is the simplest and most obvious example how broken the
> calculation in musl is:
> 
> void test10()
> {
>     time_t t = 0;
>     struct tm tm = {0};
>     char buf[64];
> 
>     tm.tm_year = 2011 - 1900;
>     tm.tm_mon = 12 - 1;
>     tm.tm_mday = 29;
>     tm.tm_hour = 0;
>     tm.tm_min = 0;
>     tm.tm_sec = 0;
>     tm.tm_isdst = 0;
> 
>     strftime(buf, sizeof buf, "%F %T %Z", &tm);
>     printf("before: %s %ld %ld\n", buf, t, calc(&tm));
> 
>     t = mktime(&tm);
> 
>     strftime(buf, sizeof buf, "%F %T %Z", &tm);
>     printf("after1: %s %ld %ld\n", buf, t, calc(&tm));
> 
>     tm.tm_mday += 1;
>     t = mktime(&tm);
> 
>     strftime(buf, sizeof buf, "%F %T %Z", &tm);
>     printf("after2: %s %ld %ld\n", buf, t, calc(&tm));
> }
> 
> TZ=Pacific/Apia
> Year is greater than 1970.
> 
> Input:
> 2011-12-29 01:00:00 -10
> 
> Add a day:
>     tm.tm_mday += 1;
>     t = mktime(&tm);
> 
> Output:
> 2011-12-29 01:00:00 -10
> 
> Musl cannot reliably increment date by a day. Incrementing struct tm
> representing 2011-12-29 01:00:00 -10 by one day leads to the same
> date.
> 
> Causing a program to loop or stack overflow.

I thought you had found a real bug here, and spent some time working
out the math by hand on paper because local time is so headbangingly
awful and confusing. In the end, the conclusion I'm left with is that
it's working just as expected.

A "spring forward" like this is just like the start of DST, except
that you can't disambiguate the does-not-exist time with an explicit
tm_isdst. So all reasoning about what happens is equivalent to the
much more familar case of start-of-DST with tm_isdst=-1.

If you take your test program and switch it to initialize with
tm_mday=31, then do -=1 instead of +=1, you'll find that it gives 
2011-12-29 01:00:00 -10 as well, only now it seems like the correct,
expected thing to happen. Any change to "fix" the case you're
complaining about would *necessarily* break this case.

You cannot iterate days by making relative changes to struct tm and
calling mktime. This just does not work. You could instead iterate
calendar day inputs yourself, throwing away duplicate outputs
(resulting from nonexistent days like this one) but that would miss
days that exist in duplicate on the calendar, where the change happens
in the opposite direction. What's probably a better approach is
iterating time_t values (or a struct tm in UTC, using timegm) then,
for each day, converting to localtime and picking a "start of day"
time in localtime.

In any case, the core issue you're hitting here is that time zones are
HARD to work with and that there is inherent complexity that libc
cannot save you from. You only got lucky that what you were trying to
do "worked" with glibc because you were iterating days forward; if you
were doing reverse, it would break exactly the same way.

Rich

  reply	other threads:[~2024-03-25 12:21 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-24 13:36 Alexander Weps
2024-03-24 16:59 ` Alexander Weps
2024-03-24 17:04 ` Rich Felker
2024-03-24 17:12   ` Alexander Weps
2024-03-24 18:00     ` Alexander Weps
2024-03-24 18:02     ` Rich Felker
2024-03-24 18:16       ` Alexander Weps
2024-03-24 18:24         ` Rich Felker
2024-03-24 18:36           ` Alexander Weps
2024-03-24 19:01             ` Joakim Sindholt
2024-03-24 19:05               ` Alexander Weps
2024-03-24 19:06             ` Alexander Weps
2024-03-24 19:13               ` Alexander Weps
2024-03-24 19:13               ` Alexander Weps
2024-03-24 19:22             ` Rich Felker
2024-03-24 19:57               ` Alexander Weps
2024-03-24 20:22                 ` Rich Felker
2024-03-24 20:50                   ` Alexander Weps
2024-03-24 21:43                     ` Alexander Weps
2024-03-24 23:51                 ` Thorsten Glaser
2024-03-25  0:36                   ` Alexander Weps
2024-03-25 11:52                     ` Alexander Weps
2024-03-25 12:21                       ` Rich Felker [this message]
2024-03-25 12:55                         ` Alexander Weps
2024-03-25 13:08                           ` Rich Felker
2024-03-25 13:13                             ` Alexander Weps
2024-03-25 13:13                           ` Rich Felker
2024-03-25 13:24                             ` Alexander Weps
2024-03-25 13:42                               ` Rich Felker
2024-03-25 13:48                                 ` Alexander Weps
2024-03-25 13:50                                   ` Alexander Weps
2024-03-25 18:02                                 ` Rich Felker
2024-03-25 18:28                                   ` Alexander Weps
2024-03-25 18:53                                     ` Rich Felker
2024-03-25 18:57                                       ` Alexander Weps
2024-03-25 19:38                                         ` Rich Felker
2024-03-25 19:47                                           ` Rich Felker
2024-03-25 20:05                                             ` Alexander Weps
2024-03-25 20:12                                               ` Alexander Weps
2024-03-25 20:00                                           ` Alexander Weps
2024-03-25 20:23                                             ` Rich Felker
2024-03-25 20:31                                               ` Rich Felker
2024-03-25 23:19                                     ` Thorsten Glaser
2024-03-25 23:16                                 ` Thorsten Glaser
2024-03-25 13:44                               ` Alexander Weps
2024-03-25 22:40                           ` Thorsten Glaser
2024-03-25 22:59                             ` Alexander Weps
2024-03-25 23:34                               ` Thorsten Glaser
2024-03-26 12:45                                 ` Alexander Weps
2024-03-26 21:59                                   ` Thorsten Glaser
2024-03-27  0:14                                     ` Alexander Weps
2024-03-27  0:38                                       ` Alexander Weps
2024-03-27  1:35                                       ` Thorsten Glaser
2024-03-27  2:45                                         ` Alexander Weps
2024-03-27  4:42                                           ` Thorsten Glaser
2024-03-26 18:56                                 ` Alexander Weps
2024-03-25 23:13                             ` Rich Felker
  -- strict thread matches above, loose matches on Subject: below --
2024-03-22 19:56 Alexander Weps
2024-03-23  6:41 ` Markus Wichmann
     [not found]   ` <528SeRFaPfDw7fA4kqKDlio1U4RB_t9nmUemPcWw9_t1e2hBDpXYFmOqxAC37szgYvAVtmTuXWsmT64SSN3cSQFVdrQqXUAgkdTMPZQ0bg0=@pm.me>
2024-03-23 10:38     ` Markus Wichmann
2024-03-23 11:59       ` Alexander Weps
2024-03-23 12:00         ` Alexander Weps
2024-03-23 12:31           ` Rich Felker
2024-03-23 13:49             ` Alexander Weps
2024-03-23 15:31               ` Rich Felker
2024-03-23 16:54                 ` Alexander Weps
2024-03-23 18:57                   ` Alexander Weps
2024-03-23 19:33                     ` Alexander Weps
2024-03-23 20:18                     ` Rich Felker
2024-03-23 20:40                       ` Alexander Weps
2024-03-24  0:36                         ` Eric Pruitt
2024-03-24  2:04                         ` Rich Felker
2024-03-24  3:32                           ` Daniel Gutson
2024-03-24 11:05                             ` Alexander Weps
2024-03-24 13:24                               ` Alexander Weps
2024-03-23 12:01         ` Alexander Weps

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240325122113.GB4163@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=exander77@pm.me \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).