From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL autolearn=ham autolearn_force=no version=3.4.4 Received: from second.openwall.net (second.openwall.net [193.110.157.125]) by inbox.vuxu.org (Postfix) with SMTP id 6D48D22135 for ; Mon, 25 Mar 2024 13:55:51 +0100 (CET) Received: (qmail 27942 invoked by uid 550); 25 Mar 2024 12:51:06 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 27907 invoked from network); 25 Mar 2024 12:51:06 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1711371338; x=1711630538; bh=W4su5g1eR1uKb/eO7puWHym+nO1eCTSNjo44QHSAN48=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=dd9GWJkuZ2tf/gVepshUwkCj4bJ1pauCu+/EDWHJXyx0jnp1zdbiHcVimXrVjYsj2 SSqTWYPxhPslHkFvzRAWKmZz/W9PEmQRw4XUv+BFt4KX6kV62X4p9XxPj8Uqso8Yvt MLiT27sE66EW/PrJsl8ctbjXrcubVE5bvqoIz1R114+LEQlaejQU8/CunNlcCQyvTi yU6tvVdLC1AH9hwiREvOPf2LzSbsleZhW6xLltI4+UwHolbUoNDFKMV1H8DHami1qr su6XrHB0gCgPuWLjsl2WpGmivO3cberEZE8xAQ64te4866ZBUmob8/WF9g8CiZQQaG 8jqmhByJ86+wA== Date: Mon, 25 Mar 2024 12:55:28 +0000 To: Rich Felker From: Alexander Weps Cc: musl@lists.openwall.com Message-ID: In-Reply-To: <20240325122113.GB4163@brightrain.aerifal.cx> References: <20240324182458.GX4163@brightrain.aerifal.cx> <9c2qfe36CoPBfKjzn1lDDZ_hfyNJCZW6-6ZTZlQgHAPr2djicIMMweEqUoQoQsDWsBt4AAZBL8vZlcsVCL950rYhcPpMDvhzDWean3oVHbs=@pm.me> <20240324192258.GY4163@brightrain.aerifal.cx> <-svm5EdX4OFN9hKzgS2FP6N1lgUGjT7edQONkAfCywgsRitwT6Vw22W3sUUGY_pnKGIXBKlujMZhPCDkJAMCYbBA5uF-IYgzhj8WB0wBE-A=@pm.me> <4YlR0YRqzZlDIOVv6SP8UDoop89n8u7BvQl_7eXNTvDZnogXMxG1z-TLGIBf-O4edUphddXGfADbk_d7Uzb37g5JoH7vOIvvNRMFDxPWZok=@pm.me> <20240325122113.GB4163@brightrain.aerifal.cx> Feedback-ID: 20507743:user:proton MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [musl] Broken mktime calculations when crossing DST boundary See below. AW On Monday, March 25th, 2024 at 13:21, Rich Felker wrote: > 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 =3D 0; > > struct tm tm =3D {0}; > > char buf[64]; > > > > tm.tm_year =3D 2011 - 1900; > > tm.tm_mon =3D 12 - 1; > > tm.tm_mday =3D 29; > > tm.tm_hour =3D 0; > > tm.tm_min =3D 0; > > tm.tm_sec =3D 0; > > tm.tm_isdst =3D 0; > > > > strftime(buf, sizeof buf, "%F %T %Z", &tm); > > printf("before: %s %ld %ld\n", buf, t, calc(&tm)); > > > > t =3D mktime(&tm); > > > > strftime(buf, sizeof buf, "%F %T %Z", &tm); > > printf("after1: %s %ld %ld\n", buf, t, calc(&tm)); > > > > tm.tm_mday +=3D 1; > > t =3D mktime(&tm); > > > > strftime(buf, sizeof buf, "%F %T %Z", &tm); > > printf("after2: %s %ld %ld\n", buf, t, calc(&tm)); > > } > > > > TZ=3DPacific/Apia > > Year is greater than 1970. > > > > Input: > > 2011-12-29 01:00:00 -10 > > > > Add a day: > > tm.tm_mday +=3D 1; > > t =3D 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. It isn't. Output from musl: 2011-12-29 01:00:00 -10 tm.tm_mday +=3D 1; t =3D mktime(&tm); 2011-12-29 01:00:00 -10 <-- date is the same after incrementing tm.tm_mday -=3D 1; t =3D mktime(&tm); 2011-12-28 01:00:00 -10 <-- going below the original date while decrementin= g Output from glibc: 2011-12-29 01:00:00 -10 tm.tm_mday +=3D 1; t =3D mktime(&tm); 2011-12-30 01:00:00 -10 <-- ok tm.tm_mday -=3D 1; t =3D mktime(&tm); 2011-12-29 01:00:00 -10 <-- ok Hour earlier (same calculations): Output from musl: 2011-12-29 00:00:00 -10 2011-12-29 00:00:00 -10 <-- date is the same after incrementing 2011-12-28 00:00:00 -10 <-- going below the original date while decrementin= g Output from glibc: 2011-12-29 00:00:00 -10 2011-12-30 00:00:00 -10 <-- ok 2011-12-29 00:00:00 -10 <-- ok Hour after (same calculations). Output from musl: 2011-12-29 02:00:00 -10 2011-12-29 02:00:00 -10 <-- date is the same after incrementing 2011-12-28 02:00:00 -10 <-- going below the original date while decrementin= g Output from glibc: 2011-12-29 02:00:00 -10 2011-12-30 02:00:00 -10 <-- ok 2011-12-29 02:00:00 -10 <-- ok What are you talking about? > > 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=3D-1. > As I said proclaimed, the issue never was about tm_isdst=3D-1. Issue is wit= h musl. > If you take your test program and switch it to initialize with > tm_mday=3D31, then do -=3D1 instead of +=3D1, 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. So (- day, +day): Musl: 2011-12-31 01:00:00 +14 2011-12-29 01:00:00 -10 2011-12-29 01:00:00 -10 Glibc: 2012-01-01 01:00:00 +14 2011-12-31 01:00:00 +14 2012-01-01 01:00:00 +14 Seems like musl doesn't even interpret the initial struct tm correctly in t= hat case. It is off by day. Because December only had 30 days, 31s day after normalization is January 1= st. So no, musl is not correct, it is even more incorrect. Jesus Christ. > > 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. I am not really commenting on this, until you sort out the above inconsiste= ncies. > > Rich