The following issue has been SUBMITTED. ====================================================================== https://austingroupbugs.net/view.php?id=1614 ====================================================================== Reported By: kre Assigned To: ====================================================================== Project: 1003.1(2016/18)/Issue7+TC2 Issue ID: 1614 Category: System Interfaces Type: Omission Severity: Objection Priority: normal Status: New Name: Robert Elz Organization: User Reference: Section: XSH 3/mktime Page Number: 1331 Line Number: 44331-44332 Interp Status: --- Final Accepted Text: ====================================================================== Date Submitted: 2022-11-03 13:36 UTC Last Modified: 2022-11-03 13:36 UTC ====================================================================== Summary: XSH 3/mktime does not specify EINVAL and should Description: First, it is possible this is a duplicate bug report, if this issue has already (or is to be already) handled by some other bug, and this report doesn't add anything new, then please simply link this to that as a duplicate, and then close this.
It is possible for the broken down local time passed to mktime() to represent a time that never existed (eg: a time in the gap (most commonly hour) when summer time commences, and the clock skips forward from NN:59 to PP:00 (usually, gaps shorter than an hour exist, but for our purposes here, as an example, that's not important) where PP==(NN+2)%24 and times MM:xx (usually for all xx) where MM==(NN+1)%24 simply never existed (with appropriate adjustments to tm_mday, etc, if the %24 makes any difference to the answer in each case). If one specifies an input time of MM:20 that simply cannot be converted to a time_t, it kind of represents NN:59 + 21 mionutes, except that local time is really PP:20 not MM:20. Note that tm_isdst does not help here, as the time simply does not exist, it cannot be either summer or standard (or standard or winter as appropriate) time. It is possible for an implementation to use tm_isdst as a hint to what happened so cases like this work timeptr = localtime(&t); timeptr->tm_min += 20; t = mktime(timeptr); where if tm_isdst should have changed value to represent the new time calculated, but clearly here does not (and since timeptr came from localtime, we know tm_isdst is 0 or 1) then the implementation might be able to guess what was intended. That does not always work however, there can be gaps in times for reasons other than the tm_isdst changing seasonal adjustment, such as when a locality decides to switch from one zone offset to another (eg: sometime, I am too lazy to look up when, Singapore and Malaysia switched from UTC+0700 to UTC+0800 (to align their clocks with Hong Kong, which was apparently considered important - at least for Singapore). Neither used summer time, before or after than change, tm_isdst is 0 in both zones - but there was an hour there that never existed. Similarly, when seasonal time ends, and time jumps backwards, there is an hour (most commonly) of local time when the time runs twice. If one specifies a time which is in (one of) those periods, along with a tm_isdst = -1, then it is impossible to determine which time_t value should apply - EINVAL is returned in that case. Note that here, tm_isdst is used to handle this overlap when it is caused by seasonal adjustments - but just as with the gap, that only works when the duplicated time are for that reason, if Malaysia decided (which would be odd, indeed, but could happen) that having their clocks match Thailand, much of Indonesia (including Jakarta), and Laos and Cambodia, rather than Singapore, they could decide to jump back to UTC+0700 by running one hour twice - with tm_isdst==0 in both occurrences. There is another way that (since bug 1533 was applied) could be considered reasonable to handle the ambiguous case - one could use the value of tm_gmtoff to determine which of the possible time_t's to return. This even handles (never seen that I am aware of, and very unlikely to ever happen) cases where a time runs more than twice, which tm_isdst cannot do. It appears very tempting to make use of that to resolve this problem, but I would strongly advise against it. Doing so would break current conforming applications (which simple addition of the fields does not) as they currently do not, and cannot (since the tm_gmtoff field does not appear in the existing standard - it is not even as of the date of this report in a published draft of an upcoming version of the standard) set that field, its value from such an application will be unitialised (or perhaps 0), if mktime() were to attempt to reference it, undefined behaviour might result. That's unacceptable. It is not even OK to permit implementations to use tm_gmtoff by making its use for this purpose unspecified, for the same reason - any implementation that does risks undefined behaviour from a currently conforming application. mktime() must not be permitted to reference that field (in the incoming structure) at all. An error code is required to handle this invalid or ambiguous input. EINVAL is the usual one. Desired Action: Between lines 44331 and 44332 (of I7 TC2) add: [EINVAL] The local time specified represents a local time which either did not exist in the past, or is not expected to exist in the future, or the local time specified represents a local time which existed, or is expected to exist in the future, more than once, and the value supplied in tm_isdst is unable to resolve the ambiguity. It might also be (assuming that you all agree with my reasoning above) a good idea to add something in the Rationale (line 44359, currently "None") explaining why tm_gmtoff is not (at least now) considered appropriate to use to resolve the ambiguous case. I will leave it up to you to determine whether it would be worth adding a Future Direction indicating that that might be changed at some future time (ie: advising applications to ensure that they start setting tm_gmtoff before calling mktime() - it will currently be ignored, but one day, might be essential in this odd case). ====================================================================== Issue History Date Modified Username Field Change ====================================================================== 2022-11-03 13:36 kre New Issue 2022-11-03 13:36 kre Name => Robert Elz 2022-11-03 13:36 kre Section => XSH 3/mktime 2022-11-03 13:36 kre Page Number => 1331 2022-11-03 13:36 kre Line Number => 44331-44332 ======================================================================