Coverage Report

Created: 2025-03-06 06:58

/src/wget/lib/mktime.c
Line
Count
Source (jump to first uncovered line)
1
/* Convert a 'struct tm' to a time_t value.
2
   Copyright (C) 1993-2025 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
   Contributed by Paul Eggert <eggert@twinsun.com>.
5
6
   The GNU C Library is free software; you can redistribute it and/or
7
   modify it under the terms of the GNU Lesser General Public
8
   License as published by the Free Software Foundation; either
9
   version 2.1 of the License, or (at your option) any later version.
10
11
   The GNU C Library is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
   Lesser General Public License for more details.
15
16
   You should have received a copy of the GNU Lesser General Public
17
   License along with the GNU C Library; if not, see
18
   <https://www.gnu.org/licenses/>.  */
19
20
/* The following macros influence what gets defined when this file is compiled:
21
22
   Macro/expression            Which gnulib module    This compilation unit
23
                                                      should define
24
25
   _LIBC                       (glibc proper)         mktime
26
27
   NEED_MKTIME_WORKING         mktime                 rpl_mktime
28
   || NEED_MKTIME_WINDOWS
29
30
   NEED_MKTIME_INTERNAL        mktime-internal        mktime_internal
31
 */
32
33
#ifndef _LIBC
34
# include <libc-config.h>
35
#endif
36
37
/* Assume that leap seconds are possible, unless told otherwise.
38
   If the host has a 'zic' command with a '-L leapsecondfilename' option,
39
   then it supports leap seconds; otherwise it probably doesn't.  */
40
#ifndef LEAP_SECONDS_POSSIBLE
41
0
# define LEAP_SECONDS_POSSIBLE 1
42
#endif
43
44
#include <time.h>
45
46
#include <errno.h>
47
#include <limits.h>
48
#include <stdbool.h>
49
#include <stdckdint.h>
50
#include <stdlib.h>
51
#include <string.h>
52
53
#include <intprops.h>
54
55
#ifndef NEED_MKTIME_INTERNAL
56
# define NEED_MKTIME_INTERNAL 0
57
#endif
58
#ifndef NEED_MKTIME_WINDOWS
59
# define NEED_MKTIME_WINDOWS 0
60
#endif
61
#ifndef NEED_MKTIME_WORKING
62
# define NEED_MKTIME_WORKING 0
63
#endif
64
65
#ifdef _LIBC
66
# include <tzset.h>
67
#endif
68
#include "mktime-internal.h"
69
70
#if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS)
71
static void
72
my_tzset (void)
73
0
{
74
# if NEED_MKTIME_WINDOWS
75
  /* Rectify the value of the environment variable TZ.
76
     There are four possible kinds of such values:
77
       - Traditional US time zone names, e.g. "PST8PDT".  Syntax: see
78
         <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset>
79
       - Time zone names based on geography, that contain one or more
80
         slashes, e.g. "Europe/Moscow".
81
       - Time zone names based on geography, without slashes, e.g.
82
         "Singapore".
83
       - Time zone names that contain explicit DST rules.  Syntax: see
84
         <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03>
85
     The Microsoft CRT understands only the first kind.  It produces incorrect
86
     results if the value of TZ is of the other kinds.
87
     But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value
88
     of the second kind for most geographies, or of the first kind in a few
89
     other geographies.  If it is of the second kind, neutralize it.  For the
90
     Microsoft CRT, an absent or empty TZ means the time zone that the user
91
     has set in the Windows Control Panel.
92
     If the value of TZ is of the third or fourth kind -- Cygwin programs
93
     understand these syntaxes as well --, it does not matter whether we
94
     neutralize it or not, since these values occur only when a Cygwin user
95
     has set TZ explicitly; this case is 1. rare and 2. under the user's
96
     responsibility.  */
97
  const char *tz = getenv ("TZ");
98
  if (tz != NULL && strchr (tz, '/') != NULL)
99
    _putenv ("TZ=");
100
# else
101
0
  tzset ();
102
0
# endif
103
0
}
104
# undef tzset
105
0
# define tzset() my_tzset ()
106
#endif
107
108
#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL
109
110
/* A signed type that can represent an integer number of years
111
   multiplied by four times the number of seconds in a year.  It is
112
   needed when converting a tm_year value times the number of seconds
113
   in a year.  The factor of four comes because these products need
114
   to be subtracted from each other, and sometimes with an offset
115
   added to them, and then with another timestamp added, without
116
   worrying about overflow.
117
118
   Much of the code uses long_int to represent __time64_t values, to
119
   lessen the hassle of dealing with platforms where __time64_t is
120
   unsigned, and because long_int should suffice to represent all
121
   __time64_t values that mktime can generate even on platforms where
122
   __time64_t is wider than the int components of struct tm.  */
123
124
# if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60
125
typedef long int long_int;
126
# else
127
typedef long long int long_int;
128
# endif
129
static_assert (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60);
130
131
/* Shift A right by B bits portably, by dividing A by 2**B and
132
   truncating towards minus infinity.  B should be in the range 0 <= B
133
   <= LONG_INT_BITS - 2, where LONG_INT_BITS is the number of useful
134
   bits in a long_int.  LONG_INT_BITS is at least 32.
135
136
   ISO C99 says that A >> B is implementation-defined if A < 0.  Some
137
   implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
138
   right in the usual way when A < 0, so SHR falls back on division if
139
   ordinary A >> B doesn't seem to be the usual signed shift.  */
140
141
static long_int
142
shr (long_int a, int b)
143
0
{
144
0
  long_int one = 1;
145
0
  return (-one >> 1 == -1
146
0
    ? a >> b
147
0
    : (a + (a < 0)) / (one << b) - (a < 0));
148
0
}
149
150
/* Bounds for the intersection of __time64_t and long_int.  */
151
152
static long_int const mktime_min
153
  = ((TYPE_SIGNED (__time64_t)
154
      && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int))
155
     ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t));
156
static long_int const mktime_max
157
  = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t)
158
     ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t));
159
160
0
# define EPOCH_YEAR 1970
161
0
# define TM_YEAR_BASE 1900
162
static_assert (TM_YEAR_BASE % 100 == 0);
163
164
/* Is YEAR + TM_YEAR_BASE a leap year?  */
165
static bool
166
leapyear (long_int year)
167
0
{
168
  /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
169
     Also, work even if YEAR is negative.  */
170
0
  return
171
0
    ((year & 3) == 0
172
0
     && (year % 100 != 0
173
0
   || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
174
0
}
175
176
/* How many days come before each month (0-12).  */
177
# ifndef _LIBC
178
static
179
# endif
180
const unsigned short int __mon_yday[2][13] =
181
  {
182
    /* Normal years.  */
183
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
184
    /* Leap years.  */
185
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
186
  };
187
188
189
/* Do the values A and B differ according to the rules for tm_isdst?
190
   A and B differ if one is zero and the other positive.  */
191
static bool
192
isdst_differ (int a, int b)
193
0
{
194
0
  return (!a != !b) && (0 <= a) && (0 <= b);
195
0
}
196
197
/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
198
   (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
199
   were not adjusted between the timestamps.
200
201
   The YEAR values uses the same numbering as TP->tm_year.  Values
202
   need not be in the usual range.  However, YEAR1 - YEAR0 must not
203
   overflow even when multiplied by three times the number of seconds
204
   in a year, and likewise for YDAY1 - YDAY0 and three times the
205
   number of seconds in a day.  */
206
207
static long_int
208
ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
209
      int year0, int yday0, int hour0, int min0, int sec0)
210
0
{
211
0
  static_assert (-1 / 2 == 0);
212
213
  /* Compute intervening leap days correctly even if year is negative.
214
     Take care to avoid integer overflow here.  */
215
0
  int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3);
216
0
  int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3);
217
0
  int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
218
0
  int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
219
0
  int a400 = shr (a100, 2);
220
0
  int b400 = shr (b100, 2);
221
0
  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
222
223
  /* Compute the desired time without overflowing.  */
224
0
  long_int years = year1 - year0;
225
0
  long_int days = 365 * years + yday1 - yday0 + intervening_leap_days;
226
0
  long_int hours = 24 * days + hour1 - hour0;
227
0
  long_int minutes = 60 * hours + min1 - min0;
228
0
  long_int seconds = 60 * minutes + sec1 - sec0;
229
0
  return seconds;
230
0
}
231
232
/* Return the average of A and B, even if A + B would overflow.
233
   Round toward positive infinity.  */
234
static long_int
235
long_int_avg (long_int a, long_int b)
236
0
{
237
0
  return shr (a, 1) + shr (b, 1) + ((a | b) & 1);
238
0
}
239
240
/* Return a long_int value corresponding to (YEAR-YDAY HOUR:MIN:SEC)
241
   minus *TP seconds, assuming no clock adjustments occurred between
242
   the two timestamps.
243
244
   YEAR and YDAY must not be so large that multiplying them by three times the
245
   number of seconds in a year (or day, respectively) would overflow long_int.
246
   *TP should be in the usual range.  */
247
static long_int
248
tm_diff (long_int year, long_int yday, int hour, int min, int sec,
249
   struct tm const *tp)
250
0
{
251
0
  return ydhms_diff (year, yday, hour, min, sec,
252
0
         tp->tm_year, tp->tm_yday,
253
0
         tp->tm_hour, tp->tm_min, tp->tm_sec);
254
0
}
255
256
#ifndef _LIBC
257
/* Convert T to a struct tm value in *TM.  Use localtime64_r if LOCAL,
258
   otherwise gmtime64_r.  T must be in range for __time64_t.  Return
259
   TM if successful, NULL (setting errno) on failure.  */
260
static struct tm *
261
convert_time (long_int t, bool local, struct tm *tm)
262
0
{
263
0
  __time64_t x = t;
264
0
  if (local)
265
0
    return __localtime64_r (&x, tm);
266
0
  else
267
0
    return __gmtime64_r (&x, tm);
268
0
}
269
0
# define __tz_convert convert_time
270
#endif
271
272
/* Convert *T to a broken down time in *TP (as if by localtime if
273
   LOCAL, otherwise as if by gmtime).  If *T is out of range for
274
   conversion, adjust it so that it is the nearest in-range value and
275
   then convert that.  A value is in range if it fits in both
276
   __time64_t and long_int.  Return TP on success, NULL (setting
277
   errno) on failure.  */
278
static struct tm *
279
ranged_convert (bool local, long_int *t, struct tm *tp)
280
0
{
281
0
  long_int t1 = (*t < mktime_min ? mktime_min
282
0
     : *t <= mktime_max ? *t : mktime_max);
283
0
  struct tm *r = __tz_convert (t1, local, tp);
284
0
  if (r)
285
0
    {
286
0
      *t = t1;
287
0
      return r;
288
0
    }
289
0
  if (errno != EOVERFLOW)
290
0
    return NULL;
291
292
0
  long_int bad = t1;
293
0
  long_int ok = 0;
294
0
  struct tm oktm; oktm.tm_sec = -1;
295
296
  /* BAD is a known out-of-range value, and OK is a known in-range one.
297
     Use binary search to narrow the range between BAD and OK until
298
     they differ by 1.  */
299
0
  while (true)
300
0
    {
301
0
      long_int mid = long_int_avg (ok, bad);
302
0
      if (mid == ok || mid == bad)
303
0
  break;
304
0
      if (__tz_convert (mid, local, tp))
305
0
  ok = mid, oktm = *tp;
306
0
      else if (errno != EOVERFLOW)
307
0
  return NULL;
308
0
      else
309
0
  bad = mid;
310
0
    }
311
312
0
  if (oktm.tm_sec < 0)
313
0
    return NULL;
314
0
  *t = ok;
315
0
  *tp = oktm;
316
0
  return tp;
317
0
}
318
319
320
/* Convert *TP to a __time64_t value.  If LOCAL, the reverse mapping
321
   is performed as if localtime, otherwise as if by gmtime.  Use
322
   *OFFSET to keep track of a guess at the offset of the result,
323
   compared to what the result would be for UTC without leap seconds.
324
   If *OFFSET's guess is correct, only one reverse mapping call is
325
   needed.  If successful, set *TP to the canonicalized struct tm;
326
   otherwise leave *TP alone, return ((time_t) -1) and set errno.
327
   This function is external because it is used also by timegm.c.
328
329
   If _LIBC, the caller must lock __tzset_lock.  */
330
__time64_t
331
__mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset)
332
0
{
333
0
  struct tm tm;
334
335
  /* The maximum number of probes should be enough to handle any
336
     combinations of time zone rule changes, solar time, leap seconds,
337
     and oscillations around a spring-forward gap.  POSIX.1 prohibits
338
     leap seconds, but some hosts have them anyway.  */
339
0
  int remaining_probes = 6;
340
341
0
#ifndef _LIBC
342
  /* Gnulib mktime doesn't lock the tz state, so it may need to probe
343
     more often if some other thread changes local time while
344
     __mktime_internal is probing.  Double the number of probes; this
345
     should suffice for practical cases that are at all likely.  */
346
0
  remaining_probes *= 2;
347
0
#endif
348
349
  /* Time requested.  Copy it in case gmtime/localtime modify *TP;
350
     this can occur if TP is localtime's returned value and CONVERT is
351
     localtime.  */
352
0
  int sec = tp->tm_sec;
353
0
  int min = tp->tm_min;
354
0
  int hour = tp->tm_hour;
355
0
  int mday = tp->tm_mday;
356
0
  int mon = tp->tm_mon;
357
0
  int year_requested = tp->tm_year;
358
0
  int isdst = tp->tm_isdst;
359
360
  /* True if the previous probe was DST.  */
361
0
  bool dst2 = false;
362
363
  /* Ensure that mon is in range, and set year accordingly.  */
364
0
  int mon_remainder = mon % 12;
365
0
  int negative_mon_remainder = mon_remainder < 0;
366
0
  int mon_years = mon / 12 - negative_mon_remainder;
367
0
  long_int lyear_requested = year_requested;
368
0
  long_int year = lyear_requested + mon_years;
369
370
  /* The other values need not be in range:
371
     the remaining code handles overflows correctly.  */
372
373
  /* Calculate day of year from year, month, and day of month.
374
     The result need not be in range.  */
375
0
  int mon_yday = ((__mon_yday[leapyear (year)]
376
0
       [mon_remainder + 12 * negative_mon_remainder])
377
0
      - 1);
378
0
  long_int lmday = mday;
379
0
  long_int yday = mon_yday + lmday;
380
381
0
  mktime_offset_t off = *offset;
382
0
  int negative_offset_guess;
383
384
0
  int sec_requested = sec;
385
386
0
  if (LEAP_SECONDS_POSSIBLE)
387
0
    {
388
      /* Handle out-of-range seconds specially,
389
   since ydhms_diff assumes every minute has 60 seconds.  */
390
0
      if (sec < 0)
391
0
  sec = 0;
392
0
      if (59 < sec)
393
0
  sec = 59;
394
0
    }
395
396
  /* Invert CONVERT by probing.  First assume the same offset as last
397
     time.  */
398
399
0
  ckd_sub (&negative_offset_guess, 0, off);
400
0
  long_int t0 = ydhms_diff (year, yday, hour, min, sec,
401
0
          EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0,
402
0
          negative_offset_guess);
403
0
  long_int t = t0, t1 = t0, t2 = t0;
404
405
  /* Repeatedly use the error to improve the guess.  */
406
407
0
  while (true)
408
0
    {
409
0
      if (! ranged_convert (local, &t, &tm))
410
0
  return -1;
411
0
      long_int dt = tm_diff (year, yday, hour, min, sec, &tm);
412
0
      if (dt == 0)
413
0
  break;
414
415
0
      if (t == t1 && t != t2
416
0
    && (tm.tm_isdst < 0
417
0
        || (isdst < 0
418
0
      ? dst2 <= (tm.tm_isdst != 0)
419
0
      : (isdst != 0) != (tm.tm_isdst != 0))))
420
  /* We can't possibly find a match, as we are oscillating
421
     between two values.  The requested time probably falls
422
     within a spring-forward gap of size DT.  Follow the common
423
     practice in this case, which is to return a time that is DT
424
     away from the requested time, preferring a time whose
425
     tm_isdst differs from the requested value.  (If no tm_isdst
426
     was requested and only one of the two values has a nonzero
427
     tm_isdst, prefer that value.)  In practice, this is more
428
     useful than returning -1.  */
429
0
  goto offset_found;
430
431
0
      remaining_probes--;
432
0
      if (remaining_probes == 0)
433
0
  {
434
0
    __set_errno (EOVERFLOW);
435
0
    return -1;
436
0
  }
437
438
0
      t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0;
439
0
    }
440
441
  /* We have a match.  Check whether tm.tm_isdst has the requested
442
     value, if any.  */
443
0
  if (isdst_differ (isdst, tm.tm_isdst))
444
0
    {
445
      /* tm.tm_isdst has the wrong value.  Look for a neighboring
446
   time with the right value, and use its UTC offset.
447
448
   Heuristic: probe the adjacent timestamps in both directions,
449
   looking for the desired isdst.  If none is found within a
450
   reasonable duration bound, ignore the disagreement.
451
   This should work for all real time zone histories in the tz
452
   database.  */
453
454
      /* Distance between probes when looking for a DST boundary.  In
455
   tzdata2003a, the shortest period of DST is 601200 seconds
456
   (e.g., America/Recife starting 2000-10-08 01:00), and the
457
   shortest period of non-DST surrounded by DST is 694800
458
   seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the
459
   minimum of these two values, so we don't miss these short
460
   periods when probing.  */
461
0
      int stride = 601200;
462
463
      /* Do not probe too far away from the requested time,
464
         by striding until at least a year has passed, but then giving up.
465
         This helps avoid unexpected results in (for example) Asia/Kolkata,
466
         for which today's users expect to see no DST even though it
467
         did observe DST long ago.  */
468
0
      int year_seconds_bound = 366 * 24 * 60 * 60 + 1;
469
0
      int delta_bound = year_seconds_bound + stride;
470
471
0
      int delta, direction;
472
473
      /* Search in both directions, closest first.  */
474
0
      for (delta = stride; delta < delta_bound; delta += stride)
475
0
  for (direction = -1; direction <= 1; direction += 2)
476
0
    {
477
0
      long_int ot;
478
0
      if (! ckd_add (&ot, t, delta * direction))
479
0
        {
480
0
    struct tm otm;
481
0
    if (! ranged_convert (local, &ot, &otm))
482
0
      return -1;
483
0
    if (! isdst_differ (isdst, otm.tm_isdst))
484
0
      {
485
        /* We found the desired tm_isdst.
486
           Extrapolate back to the desired time.  */
487
0
        long_int gt = ot + tm_diff (year, yday, hour, min, sec,
488
0
            &otm);
489
0
        if (mktime_min <= gt && gt <= mktime_max)
490
0
          {
491
0
      if (__tz_convert (gt, local, &tm))
492
0
        {
493
0
          t = gt;
494
0
          goto offset_found;
495
0
        }
496
0
      if (errno != EOVERFLOW)
497
0
        return -1;
498
0
          }
499
0
      }
500
0
        }
501
0
    }
502
503
      /* No probe with the requested tm_isdst was found nearby.
504
         Ignore the requested tm_isdst.  */
505
0
    }
506
507
0
 offset_found:
508
  /* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS.
509
     This is just a heuristic to speed up the next mktime call, and
510
     correctness is unaffected if integer overflow occurs here.  */
511
0
  ckd_sub (offset, t, t0);
512
0
  ckd_sub (offset, *offset, negative_offset_guess);
513
514
0
  if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
515
0
    {
516
      /* Adjust time to reflect the tm_sec requested, not the normalized value.
517
   Also, repair any damage from a false match due to a leap second.  */
518
0
      long_int sec_adjustment = sec == 0 && tm.tm_sec == 60;
519
0
      sec_adjustment -= sec;
520
0
      sec_adjustment += sec_requested;
521
0
      if (ckd_add (&t, t, sec_adjustment)
522
0
    || ! (mktime_min <= t && t <= mktime_max))
523
0
  {
524
0
    __set_errno (EOVERFLOW);
525
0
    return -1;
526
0
  }
527
0
      if (! __tz_convert (t, local, &tm))
528
0
  return -1;
529
0
    }
530
531
0
  *tp = tm;
532
0
  return t;
533
0
}
534
535
#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */
536
537
#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS
538
539
/* Convert *TP to a __time64_t value.  */
540
__time64_t
541
__mktime64 (struct tm *tp)
542
0
{
543
0
  __libc_lock_lock (__tzset_lock);
544
0
  __tzset_unlocked ();
545
546
0
# if defined _LIBC || NEED_MKTIME_WORKING
547
0
  static mktime_offset_t localtime_offset;
548
0
  __time64_t result = __mktime_internal (tp, true, &localtime_offset);
549
# else
550
#  undef mktime
551
  __time64_t result = mktime (tp);
552
# endif
553
554
0
  __libc_lock_unlock (__tzset_lock);
555
0
  return result;
556
0
}
557
#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */
558
559
#if defined _LIBC && __TIMESIZE != 64
560
561
libc_hidden_def (__mktime64)
562
563
time_t
564
mktime (struct tm *tp)
565
{
566
  struct tm tm = *tp;
567
  __time64_t t = __mktime64 (&tm);
568
  if (in_time_t_range (t))
569
    {
570
      *tp = tm;
571
      return t;
572
    }
573
  else
574
    {
575
      __set_errno (EOVERFLOW);
576
      return -1;
577
    }
578
}
579
580
#endif
581
582
weak_alias (mktime, timelocal)
583
libc_hidden_def (mktime)
584
libc_hidden_weak (timelocal)