Coverage Report

Created: 2024-09-06 06:25

/src/dovecot/src/lib/utc-mktime.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
2
3
#include "lib.h"
4
#include "utc-mktime.h"
5
6
static int tm_cmp(const struct tm *tm1, const struct tm *tm2)
7
0
{
8
0
  int diff;
9
10
0
  if ((diff = tm1->tm_year - tm2->tm_year) != 0)
11
0
    return diff;
12
0
  if ((diff = tm1->tm_mon - tm2->tm_mon) != 0)
13
0
    return diff;
14
0
  if ((diff = tm1->tm_mday - tm2->tm_mday) != 0)
15
0
    return diff;
16
0
  if ((diff = tm1->tm_hour - tm2->tm_hour) != 0)
17
0
    return diff;
18
0
  if ((diff = tm1->tm_min - tm2->tm_min) != 0)
19
0
    return diff;
20
0
  return tm1->tm_sec - tm2->tm_sec;
21
0
}
22
23
static inline void adjust_leap_second(struct tm *tm)
24
0
{
25
0
  if (tm->tm_sec == 60)
26
0
    tm->tm_sec = 59;
27
0
}
28
29
#ifdef HAVE_TIMEGM
30
/* Normalization done by timegm is considered a failure here, since it means
31
 * the timestamp is not valid as-is. Leap second 60 is adjusted to 59 before
32
 * this though. */
33
time_t utc_mktime(const struct tm *tm)
34
0
{
35
0
  struct tm leap_adj_tm = *tm;
36
0
  adjust_leap_second(&leap_adj_tm);
37
0
  struct tm tmp = leap_adj_tm;
38
0
  time_t t;
39
40
0
  t = timegm(&tmp);
41
0
  if (tm_cmp(&leap_adj_tm, &tmp) != 0)
42
0
    return (time_t)-1;
43
0
  return t;
44
0
}
45
#else
46
time_t utc_mktime(const struct tm *tm)
47
{
48
  struct tm leap_adj_tm = *tm;
49
  adjust_leap_second(&leap_adj_tm);
50
  const struct tm *try_tm;
51
  time_t t;
52
  int bits, dir;
53
54
  /* we'll do a binary search across the entire valid time_t range.
55
     when gmtime()'s output matches the tm parameter, we've found the
56
     correct time_t value. this also means that if tm contains invalid
57
     values, -1 is returned. */
58
#ifdef TIME_T_SIGNED
59
  t = 0;
60
#else
61
  t = (time_t)1 << (TIME_T_MAX_BITS - 1);
62
#endif
63
  for (bits = TIME_T_MAX_BITS - 2;; bits--) {
64
    try_tm = gmtime(&t);
65
    dir = tm_cmp(&leap_adj_tm, try_tm);
66
    if (dir == 0)
67
      return t;
68
    if (bits < 0)
69
      break;
70
71
    if (dir < 0)
72
      t -= (time_t)1 << bits;
73
    else
74
      t += (time_t)1 << bits;
75
  }
76
77
  return (time_t)-1;
78
}
79
#endif