Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Pine.BSM.4.64L.2403252251450.3887@herc.mirbsd.org>
Date: Mon, 25 Mar 2024 23:16:05 +0000 (UTC)
From: Thorsten Glaser <tg@...bsd.de>
To: musl@...ts.openwall.com
Subject: Re: Broken mktime calculations when crossing DST boundary

I wrote (in another mail):

> tbh I’d expect this to end up in 1325239199=2011-12-29 23:59:59
> instead of 2011-12-29 01:00:00 though, at least from reading the
> latest Issue 8 proofreading draft. WDYT dalias?

Looking at the spec again, my expectation was wrong, the…

| […] and the broken-down time corresponds to a time that was (or will
| be) skipped over or repeated due to the occurrence of such a change,
| mktime() shall calculate the time since the Epoch value using either
| the offset in effect before the change or the offset in effect after
| the change.

… doesn’t yield this. In fact, further down, we have:

| If a geographical timezone changes its UTC offset such that “old
| 00:00” becomes “new 00:30” and mktime() is given 00:20, it treats that
| as either 20 minutes after “old 00:00” or 10 minutes before “new
| 00:30”, and gives back appropriately altered struct tm fields.

This entirely specifies how this is to be handled… (more below).


Rich Felker dixit:

>Hopefully that will clarify things for you. On musl you will see:
>
>normalized input: 2011-12-29 00:00:00 -10
>+1day per mktime: 2011-12-29 00:00:00 -10
>+1day via time_t: 2011-12-31 00:00:00 +14
>-1day per mktime: 2011-12-28 00:00:00 -10
>-1day via time_t: 2011-12-28 00:00:00 -10
>
>normalized input: 2011-12-31 00:00:00 +14
>+1day per mktime: 2012-01-01 00:00:00 +14
>+1day via time_t: 2012-01-01 00:00:00 +14
>-1day per mktime: 2011-12-29 00:00:00 -10
>-1day via time_t: 2011-12-29 00:00:00 -10
>
>You can see what you get on glibc.

Debian 11 (glibc 2.31) amd64:

$ TZ=Pacific/Apia ./mktime_rel "2011-12-29 00:00:00"
normalized input: 2011-12-29 00:00:00 -10
mktime day+1: Value too large for defined data type
+1day via time_t: 2011-12-31 00:00:00 +14
-1day per mktime: 2011-12-28 00:00:00 -10
-1day via time_t: 2011-12-28 00:00:00 -10
$ TZ=Pacific/Apia ./mktime_rel "2011-12-31 00:00:00"
normalized input: 2011-12-31 00:00:00 +14
+1day per mktime: 2012-01-01 00:00:00 +14
+1day via time_t: 2012-01-01 00:00:00 +14
mktime day-1: Value too large for defined data type
-1day via time_t: 2011-12-29 00:00:00 -10

Same on sid.

Looking at the spec excerpt from above, I think returning EOVERFLOW
is not permitted here, so glibc has something to fix…

MirBSD/i386:

$ TZ=Pacific/Apia ./mktime_rel "2011-12-29 00:00:00"
normalized input: 2011-12-29 00:00:00 -10
+1day per mktime: 2011-12-30 00:00:00 -10   ← how? probably bug in old tzcode
+1day via time_t: 2011-12-31 00:00:00 +14
-1day per mktime: 2011-12-28 00:00:00 -10
-1day via time_t: 2011-12-28 00:00:00 -10
$ TZ=Pacific/Apia ./mktime_rel "2011-12-31 00:00:00"
normalized input: 2011-12-31 00:00:00 +14
+1day per mktime: 2012-01-01 00:00:00 +14
+1day via time_t: 2012-01-01 00:00:00 +14
-1day per mktime: 2011-12-30 00:00:00 +14   ← how? probably bug in old tzcode
-1day via time_t: 2011-12-29 00:00:00 -10

I think I’ll have a bug to fix there ;)
But that code is ancient and doesn’t yet know
about all those new standards…


Looking at the spec excerpt from above again, what we have
is a discontinuity…

$ TZ=Pacific/Apia date -d @1325239199
Thu Dec 29 23:59:59 -10 2011
$ TZ=Pacific/Apia date -d @1325239200
Sat Dec 31 00:00:00 +14 2011

… and an incoming request via struct tm of, let’s say:

2011-12-30 01:00:00

From the excerpt above, mktime can now treat this as either
1 hour after “old 2011-12-30 00:00:00” or 23 hours before
“new 2011-12-31 00:00:00”.

Old 2011-12-30 00:00:00 becomes new 2011-12-31 00:00:00,
so in the first case, the expected result is indeed
2011-12-31 01:00:00 (independent of whether one is going
up or down!), and 23 hours before new 2011-12-31 00:00:00
becomes 23 hours before old 2011-12-30 00:00:00 becomes
2011-12-29 01:00:00. Which is what musl returns, which
means indeed musl DTRT here.

bye,
//mirabilos
-- 
“It is inappropriate to require that a time represented as
 seconds since the Epoch precisely represent the number of
 seconds between the referenced time and the Epoch.”
	-- IEEE Std 1003.1b-1993 (POSIX) Section B.2.2.2

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.