1 /*        $NetBSD: localtime.c,v 1.147 2025/01/31 22:08:18 christos Exp $       */
2 
3 /* Convert timestamp from time_t to struct tm.  */
4 
5 /*
6 ** This file is in the public domain, so clarified as of
7 ** 1996-06-05 by Arthur David Olson.
8 */
9 
10 #include <sys/cdefs.h>
11 #if defined(LIBC_SCCS) && !defined(lint)
12 #if 0
13 static char         elsieid[] = "@(#)localtime.c  8.17";
14 #else
15 __RCSID("$NetBSD: localtime.c,v 1.147 2025/01/31 22:08:18 christos Exp $");
16 #endif
17 #endif /* LIBC_SCCS and not lint */
18 
19 /*
20 ** Leap second handling from Bradley White.
21 ** POSIX.1-1988 style TZ environment variable handling from Guy Harris.
22 */
23 
24 /*LINTLIBRARY*/
25 
26 #include "namespace.h"
27 #include <assert.h>
28 #define LOCALTIME_IMPLEMENTATION
29 #include "private.h"
30 
31 #include "tzfile.h"
32 #include <fcntl.h>
33 
34 #if defined(__weak_alias)
35 __weak_alias(daylight,_daylight)
36 __weak_alias(tzname,_tzname)
37 #endif
38 
39 #if HAVE_SYS_STAT_H
40 # include <sys/stat.h>
41 #endif
42 #if !defined S_ISREG && defined S_IFREG
43 /* Ancient UNIX or recent MS-Windows.  */
44 # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
45 #endif
46 
47 #ifdef __NetBSD__
48 #define lock() (rwlock_wrlock(&__lcl_lock), 0)
49 #define unlock() rwlock_unlock(&__lcl_lock)
50 #else
51 #if defined THREAD_SAFE && THREAD_SAFE
52 # include <pthread.h>
53 static pthread_mutex_t locallock = PTHREAD_MUTEX_INITIALIZER;
54 static int lock(void) { return pthread_mutex_lock(&locallock); }
55 static void unlock(void) { pthread_mutex_unlock(&locallock); }
56 #else
57 static int lock(void) { return 0; }
58 static void unlock(void) { }
59 #endif
60 #endif
61 
62 /* Unless intptr_t is missing, pacify gcc -Wcast-qual on char const * exprs.
63    Use this carefully, as the casts disable type checking.
64    This is a macro so that it can be used in static initializers.  */
65 #ifdef INTPTR_MAX
66 # define UNCONST(a) ((char *) (intptr_t) (a))
67 #else
68 # define UNCONST(a) ((char *) (a))
69 #endif
70 
71 /* A signed type wider than int, so that we can add 1900 + tm_mon/12 to tm_year
72    without overflow.  The static_assert checks that it is indeed wider
73    than int; if this fails on your platform please let us know.  */
74 #if INT_MAX < LONG_MAX
75 typedef long iinntt;
76 # define IINNTT_MIN LONG_MIN
77 # define IINNTT_MAX LONG_MAX
78 #elif INT_MAX < LLONG_MAX
79 typedef long long iinntt;
80 # define IINNTT_MIN LLONG_MIN
81 # define IINNTT_MAX LLONG_MAX
82 #else
83 typedef intmax_t iinntt;
84 # define IINNTT_MIN INTMAX_MIN
85 # define IINNTT_MAX INTMAX_MAX
86 #endif
87 /*CONSTCOND*/
88 static_assert(IINNTT_MIN < INT_MIN && INT_MAX < IINNTT_MAX);
89 
90 /* On platforms where offtime or mktime might overflow,
91    strftime.c defines USE_TIMEX_T to be true and includes us.
92    This tells us to #define time_t to an internal type timex_t that is
93    wide enough so that strftime %s never suffers from integer overflow,
94    and to #define offtime (if TM_GMTOFF is defined) or mktime (otherwise)
95    to a static function that returns the redefined time_t.
96    It also tells us to define only data and code needed
97    to support the offtime or mktime variant.  */
98 #ifndef USE_TIMEX_T
99 # define USE_TIMEX_T false
100 #endif
101 #if USE_TIMEX_T
102 # undef TIME_T_MIN
103 # undef TIME_T_MAX
104 # undef time_t
105 # define time_t timex_t
106 # if MKTIME_FITS_IN(LONG_MIN, LONG_MAX)
107 typedef long timex_t;
108 # define TIME_T_MIN LONG_MIN
109 # define TIME_T_MAX LONG_MAX
110 # elif MKTIME_FITS_IN(LLONG_MIN, LLONG_MAX)
111 typedef long long timex_t;
112 # define TIME_T_MIN LLONG_MIN
113 # define TIME_T_MAX LLONG_MAX
114 # else
115 typedef intmax_t timex_t;
116 # define TIME_T_MIN INTMAX_MIN
117 # define TIME_T_MAX INTMAX_MAX
118 # endif
119 
120 # ifdef TM_GMTOFF
121 #  undef timeoff
122 #  define timeoff timex_timeoff
123 #  undef EXTERN_TIMEOFF
124 # else
125 #  undef mktime
126 #  define mktime timex_mktime
127 # endif
128 #endif
129 
130 #ifndef TZ_ABBR_CHAR_SET
131 # define TZ_ABBR_CHAR_SET \
132           "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
133 #endif /* !defined TZ_ABBR_CHAR_SET */
134 
135 #ifndef TZ_ABBR_ERR_CHAR
136 # define TZ_ABBR_ERR_CHAR '_'
137 #endif /* !defined TZ_ABBR_ERR_CHAR */
138 
139 /* Port to platforms that lack some O_* flags.  Unless otherwise
140    specified, the flags are standardized by POSIX.  */
141 
142 #ifndef O_BINARY
143 # define O_BINARY 0 /* MS-Windows */
144 #endif
145 #ifndef O_CLOEXEC
146 # define O_CLOEXEC 0
147 #endif
148 #ifndef O_CLOFORK
149 # define O_CLOFORK 0
150 #endif
151 #ifndef O_IGNORE_CTTY
152 # define O_IGNORE_CTTY 0 /* GNU/Hurd */
153 #endif
154 #ifndef O_NOCTTY
155 # define O_NOCTTY 0
156 #endif
157 
158 #ifndef WILDABBR
159 /*
160 ** Someone might make incorrect use of a time zone abbreviation:
161 **        1.        They might reference tzname[0] before calling tzset (explicitly
162 **                  or implicitly).
163 **        2.        They might reference tzname[1] before calling tzset (explicitly
164 **                  or implicitly).
165 **        3.        They might reference tzname[1] after setting to a time zone
166 **                  in which Daylight Saving Time is never observed.
167 **        4.        They might reference tzname[0] after setting to a time zone
168 **                  in which Standard Time is never observed.
169 **        5.        They might reference tm.TM_ZONE after calling offtime.
170 ** What's best to do in the above cases is open to debate;
171 ** for now, we just set things up so that in any of the five cases
172 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
173 ** string "tzname[0] used before set", and similarly for the other cases.
174 ** And another: initialize tzname[0] to "ERA", with an explanation in the
175 ** manual page of what this "time zone abbreviation" means (doing this so
176 ** that tzname[0] has the "normal" length of three characters).
177 */
178 # define WILDABBR "   "
179 #endif /* !defined WILDABBR */
180 
181 static const char   wildabbr[] = WILDABBR;
182 
183 static char const etc_utc[] = "Etc/UTC";
184 
185 #if !USE_TIMEX_T || defined TM_ZONE || !defined TM_GMTOFF
186 static char const *utc = etc_utc + sizeof "Etc/" - 1;
187 #endif
188 
189 /*
190 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
191 ** Default to US rules as of 2017-05-07.
192 ** POSIX does not specify the default DST rules;
193 ** for historical reasons, US rules are a common default.
194 */
195 #ifndef TZDEFRULESTRING
196 # define TZDEFRULESTRING ",M3.2.0,M11.1.0"
197 #endif
198 
199 typedef int_fast64_t __time_t;
200 
201 /* Limit to time zone abbreviation length in proleptic TZ strings.
202    This is distinct from TZ_MAX_CHARS, which limits TZif file contents.
203    It defaults to 254, not 255, so that desigidx_type can be an unsigned char.
204    unsigned char suffices for TZif files, so the only reason to increase
205    TZNAME_MAXIMUM is to support TZ strings specifying abbreviations
206    longer than 254 bytes.  There is little reason to do that, though,
207    as strings that long are hardly "abbreviations".  */
208 #ifndef TZNAME_MAXIMUM
209 # define TZNAME_MAXIMUM 254
210 #endif
211 
212 #if TZNAME_MAXIMUM < UCHAR_MAX
213 typedef unsigned char desigidx_type;
214 #elif TZNAME_MAXIMUM < INT_MAX
215 typedef int desigidx_type;
216 #elif TZNAME_MAXIMUM < PTRDIFF_MAX
217 typedef ptrdiff_t desigidx_type;
218 #else
219 # error "TZNAME_MAXIMUM too large"
220 #endif
221 
222 struct ttinfo {                                   /* time type information */
223           int_least32_t       tt_utoff; /* UT offset in seconds */
224           desigidx_type       tt_desigidx;        /* abbreviation list index */
225           bool                tt_isdst; /* used to set tm_isdst */
226           bool                tt_ttisstd;         /* transition is std time */
227           bool                tt_ttisut;          /* transition is UT */
228 };
229 
230 struct lsinfo {                                   /* leap second information */
231           __time_t  ls_trans; /* transition time */
232           int_fast32_t        ls_corr;  /* correction to apply */
233 };
234 
235 /* This abbreviation means local time is unspecified.  */
236 static char const UNSPEC[] = "-00";
237 
238 /* How many extra bytes are needed at the end of struct state's chars array.
239    This needs to be at least 1 for null termination in case the input
240    data isn't properly terminated, and it also needs to be big enough
241    for ttunspecified to work without crashing.  */
242 enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 };
243 
244 #define state __state
245 /* A representation of the contents of a TZif file.  Ideally this
246    would have no size limits; the following sizes should suffice for
247    practical use.  This struct should not be too large, as instances
248    are put on the stack and stacks are relatively small on some platforms.
249    See tzfile.h for more about the sizes.  */
250 struct state {
251           int                 leapcnt;
252           int                 timecnt;
253           int                 typecnt;
254           int                 charcnt;
255           bool                goback;
256           bool                goahead;
257           __time_t  ats[TZ_MAX_TIMES];
258           unsigned char       types[TZ_MAX_TIMES];
259           struct ttinfo       ttis[TZ_MAX_TYPES];
260           /*CONSTCOND*/
261           char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"),
262                            2 * (TZNAME_MAXIMUM + 1))];
263           struct lsinfo       lsis[TZ_MAX_LEAPS];
264 };
265 
266 enum r_type {
267   JULIAN_DAY,                 /* Jn = Julian day */
268   DAY_OF_YEAR,                /* n = day of year */
269   MONTH_NTH_DAY_OF_WEEK       /* Mm.n.d = month, week, day of week */
270 };
271 
272 struct rule {
273           enum r_type         r_type;             /* type of rule */
274           int                 r_day;              /* day number of rule */
275           int                 r_week;             /* week number of rule */
276           int                 r_mon;              /* month number of rule */
277           int_fast32_t        r_time;             /* transition time of rule */
278 };
279 
280 static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
281                                struct tm *);
282 static bool increment_overflow(int *, int);
283 static bool increment_overflow_time(__time_t *, int_fast32_t);
284 static int_fast32_t leapcorr(struct state const *, __time_t);
285 static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
286                                 struct tm *);
287 static bool tzparse(char const *, struct state *, struct state const *);
288 
289 #ifndef ALL_STATE
290 static struct state *  gmtptr;
291 #else
292 static struct state gmtmem;
293 static struct state *const gmtptr = &gmtmem;
294 #endif
295 
296 #ifndef TZ_STRLEN_MAX
297 # define TZ_STRLEN_MAX 255
298 #endif /* !defined TZ_STRLEN_MAX */
299 
300 #if !USE_TIMEX_T || !defined TM_GMTOFF
301 static char                   lcl_TZname[TZ_STRLEN_MAX + 1];
302 static int                    lcl_is_set;
303 #endif
304 
305 
306 #if !defined(__LIBC12_SOURCE__)
307 # ifndef ALL_STATE
308 struct state * __lclptr;
309 # else
310 static struct state lclmem;
311 struct state *const __lclptr = &lclmem;
312 # endif
313 # ifdef _REENTRANT
314 rwlock_t __lcl_lock = RWLOCK_INITIALIZER;
315 # endif
316 #endif
317 
318 /*
319 ** Section 4.12.3 of X3.159-1989 requires that
320 **        Except for the strftime function, these functions [asctime,
321 **        ctime, gmtime, localtime] return values in one of two static
322 **        objects: a broken-down time structure and an array of char.
323 ** Thanks to Paul Eggert for noting this.
324 **
325 ** Although this requirement was removed in C99 it is still present in POSIX.
326 ** Follow the requirement if SUPPORT_C89, even though this is more likely to
327 ** trigger latent bugs in programs.
328 */
329 
330 #if !USE_TIMEX_T
331 
332 # if SUPPORT_C89
333 static struct tm    tm;
334 # endif
335 
336 # if 2 <= HAVE_TZNAME + TZ_TIME_T || defined(__NetBSD__)
337 #  if !defined(__LIBC12_SOURCE__)
338 __aconst char *tzname[2] = {
339           (__aconst char *) UNCONST(wildabbr),
340           (__aconst char *) UNCONST(wildabbr),
341 };
342 #  else
343 
344 extern __aconst char *        tzname[2];
345 
346 #  endif /* __LIBC12_SOURCE__ */
347 # endif
348 
349 # if 2 <= USG_COMPAT + TZ_TIME_T || defined(__NetBSD__)
350 #  if !defined(__LIBC12_SOURCE__)
351 long                          timezone = 0;
352 int                           daylight = 0;
353 #  endif /* __LIBC12_SOURCE__ */
354 # endif /* 2<= USG_COMPAT + TZ_TIME_T */
355 
356 # if 2 <= ALTZONE + TZ_TIME_T
357 long                          altzone = 0;
358 # endif /* 2 <= ALTZONE + TZ_TIME_T */
359 #endif
360 
361 /* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX.  */
362 static void
init_ttinfo(struct ttinfo * s,int_fast32_t utoff,bool isdst,desigidx_type desigidx)363 init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst,
364               desigidx_type desigidx)
365 {
366   s->tt_utoff = (int_least32_t)utoff;
367   s->tt_isdst = isdst;
368   s->tt_desigidx = desigidx;
369   s->tt_ttisstd = false;
370   s->tt_ttisut = false;
371 }
372 
373 /* Return true if SP's time type I does not specify local time.  */
374 static bool
ttunspecified(struct state const * sp,int i)375 ttunspecified(struct state const *sp, int i)
376 {
377   char const *abbr = &sp->chars[sp->ttis[i].tt_desigidx];
378   /* memcmp is likely faster than strcmp, and is safe due to CHARS_EXTRA.  */
379   return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0;
380 }
381 
382 static int_fast32_t
detzcode(const char * const codep)383 detzcode(const char *const codep)
384 {
385           register int_fast32_t         result;
386           register int                  i;
387           int_fast32_t one = 1;
388           int_fast32_t halfmaxval = one << (32 - 2);
389           int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
390           int_fast32_t minval = -1 - maxval;
391 
392           result = codep[0] & 0x7f;
393           for (i = 1; i < 4; ++i)
394                     result = (result << 8) | (codep[i] & 0xff);
395 
396           if (codep[0] & 0x80) {
397             /* Do two's-complement negation even on non-two's-complement machines.
398                If the result would be minval - 1, return minval.  */
399             result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
400             result += minval;
401           }
402           return result;
403 }
404 
405 static int_fast64_t
detzcode64(const char * const codep)406 detzcode64(const char *const codep)
407 {
408           register int_fast64_t result;
409           register int        i;
410           int_fast64_t one = 1;
411           int_fast64_t halfmaxval = one << (64 - 2);
412           int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
413           int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
414 
415           result = codep[0] & 0x7f;
416           for (i = 1; i < 8; ++i)
417                     result = (result << 8) | (codep[i] & 0xff);
418 
419           if (codep[0] & 0x80) {
420             /* Do two's-complement negation even on non-two's-complement machines.
421                If the result would be minval - 1, return minval.  */
422             result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
423             result += minval;
424           }
425           return result;
426 }
427 
428 #include <stdio.h>
429 
430 const char *
tzgetname(const timezone_t sp,int isdst)431 tzgetname(const timezone_t sp, int isdst)
432 {
433           int i;
434           const char *name = NULL;
435           for (i = 0; i < sp->typecnt; ++i) {
436                     const struct ttinfo *const ttisp = &sp->ttis[i];
437                     if (ttisp->tt_isdst == isdst)
438                               name = &sp->chars[ttisp->tt_desigidx];
439           }
440           if (name != NULL)
441                     return name;
442           errno = ESRCH;
443           return NULL;
444 }
445 
446 long
tzgetgmtoff(const timezone_t sp,int isdst)447 tzgetgmtoff(const timezone_t sp, int isdst)
448 {
449           int i;
450           long l = -1;
451           for (i = 0; i < sp->typecnt; ++i) {
452                     const struct ttinfo *const ttisp = &sp->ttis[i];
453 
454                     if (ttisp->tt_isdst == isdst) {
455                               l = ttisp->tt_utoff;
456                     }
457           }
458           if (l == -1)
459                     errno = ESRCH;
460           return l;
461 }
462 
463 #if !USE_TIMEX_T || !defined TM_GMTOFF
464 
465 static void
update_tzname_etc(struct state const * sp,struct ttinfo const * ttisp)466 update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
467 {
468 # if HAVE_TZNAME
469   tzname[ttisp->tt_isdst] = UNCONST(&sp->chars[ttisp->tt_desigidx]);
470 # endif
471 # if USG_COMPAT
472   if (!ttisp->tt_isdst)
473     timezone = - ttisp->tt_utoff;
474 # endif
475 # if ALTZONE
476   if (ttisp->tt_isdst)
477     altzone = - ttisp->tt_utoff;
478 # endif
479 }
480 
481 /* If STDDST_MASK indicates that SP's TYPE provides useful info,
482    update tzname, timezone, and/or altzone and return STDDST_MASK,
483    diminished by the provided info if it is a specified local time.
484    Otherwise, return STDDST_MASK.  See settzname for STDDST_MASK.  */
485 static int
may_update_tzname_etc(int stddst_mask,struct state * sp,int type)486 may_update_tzname_etc(int stddst_mask, struct state *sp, int type)
487 {
488   struct ttinfo *ttisp = &sp->ttis[type];
489   int this_bit = 1 << ttisp->tt_isdst;
490   if (stddst_mask & this_bit) {
491     update_tzname_etc(sp, ttisp);
492     if (!ttunspecified(sp, type))
493       return stddst_mask & ~this_bit;
494   }
495   return stddst_mask;
496 }
497 
498 static void
settzname(void)499 settzname(void)
500 {
501           register timezone_t const     sp = __lclptr;
502           register int                            i;
503 
504           /* If STDDST_MASK & 1 we need info about a standard time.
505              If STDDST_MASK & 2 we need info about a daylight saving time.
506              When STDDST_MASK becomes zero we can stop looking.  */
507           int stddst_mask = 0;
508 
509 # if HAVE_TZNAME
510           tzname[0] = tzname[1] = UNCONST(sp ? wildabbr : utc);
511           stddst_mask = 3;
512 # endif
513 # if USG_COMPAT
514           timezone = 0;
515           stddst_mask = 3;
516 # endif
517 # if ALTZONE
518           altzone = 0;
519           stddst_mask |= 2;
520 # endif
521           /*
522           ** And to get the latest time zone abbreviations into tzname. . .
523           */
524           if (sp) {
525             for (i = sp->timecnt - 1; stddst_mask && 0 <= i; i--)
526               stddst_mask = may_update_tzname_etc(stddst_mask, sp, sp->types[i]);
527             for (i = sp->typecnt - 1; stddst_mask && 0 <= i; i--)
528               stddst_mask = may_update_tzname_etc(stddst_mask, sp, i);
529           }
530 
531 # if USG_COMPAT
532           daylight = (unsigned int)stddst_mask >> 1 ^ 1;
533 # endif
534 }
535 
536 /* Replace bogus characters in time zone abbreviations.
537    Return 0 on success, an errno value if a time zone abbreviation is
538    too long.  */
539 static int
scrub_abbrs(struct state * sp)540 scrub_abbrs(struct state *sp)
541 {
542           int i;
543 
544           /* Reject overlong abbreviations.  */
545           for (i = 0; i < sp->charcnt - (TZNAME_MAXIMUM + 1); ) {
546             int len = (int)strlen(&sp->chars[i]);
547             if (TZNAME_MAXIMUM < len)
548               return EOVERFLOW;
549             i += len + 1;
550           }
551 
552           /* Replace bogus characters.  */
553           for (i = 0; i < sp->charcnt; ++i)
554                     if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
555                               sp->chars[i] = TZ_ABBR_ERR_CHAR;
556 
557           return 0;
558 }
559 
560 #endif
561 
562 /* Input buffer for data read from a compiled tz file.  */
563 union input_buffer {
564   /* The first part of the buffer, interpreted as a header.  */
565   struct tzhead tzhead;
566 
567   /* The entire buffer.  Ideally this would have no size limits;
568      the following should suffice for practical use.  */
569   char buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
570              + 4 * TZ_MAX_TIMES];
571 };
572 
573 /* TZDIR with a trailing '/' rather than a trailing '\0'.  */
574 static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
575 
576 /* Local storage needed for 'tzloadbody'.  */
577 union local_storage {
578   /* The results of analyzing the file's contents after it is opened.  */
579   struct file_analysis {
580     /* The input buffer.  */
581     union input_buffer u;
582 
583     /* A temporary state used for parsing a TZ string in the file.  */
584     struct state st;
585   } u;
586 
587   /* The name of the file to be opened.  Ideally this would have no
588      size limits, to support arbitrarily long Zone names.
589      Limiting Zone names to 1024 bytes should suffice for practical use.
590      However, there is no need for this to be smaller than struct
591      file_analysis as that struct is allocated anyway, as the other
592      union member.  */
593   char fullname[max(sizeof(struct file_analysis), sizeof tzdirslash + 1024)];
594 };
595 
596 /* These tzload flags can be ORed together, and fit into 'char'.  */
597 enum { TZLOAD_FROMENV = 1 }; /* The TZ string came from the environment.  */
598 enum { TZLOAD_TZSTRING = 2 }; /* Read any newline-surrounded TZ string.  */
599 
600 /* Load tz data from the file named NAME into *SP.  Respect TZLOADFLAGS.
601    Use *LSP for temporary storage.  Return 0 on
602    success, an errno value on failure.  */
603 static int
tzloadbody(char const * name,struct state * sp,char tzloadflags,union local_storage * lsp)604 tzloadbody(char const *name, struct state *sp, char tzloadflags,
605              union local_storage *lsp)
606 {
607           register int                            i;
608           register int                            fid;
609           register int                            stored;
610           register ssize_t              nread;
611           register bool doaccess;
612           register union input_buffer *up = &lsp->u.u;
613           register size_t tzheadsize = sizeof(struct tzhead);
614 
615           sp->goback = sp->goahead = false;
616 
617           if (! name) {
618                     name = TZDEFAULT;
619                     if (! name)
620                       return EINVAL;
621           }
622 
623           if (name[0] == ':')
624                     ++name;
625 #ifdef SUPPRESS_TZDIR
626           /* Do not prepend TZDIR.  This is intended for specialized
627              applications only, due to its security implications.  */
628           doaccess = true;
629 #else
630           doaccess = name[0] == '/';
631 #endif
632           if (!doaccess) {
633                     char const *dot;
634                     if (sizeof lsp->fullname - sizeof tzdirslash <= strlen(name))
635                       return ENAMETOOLONG;
636 
637                     /* Create a string "TZDIR/NAME".  Using sprintf here
638                        would pull in stdio (and would fail if the
639                        resulting string length exceeded INT_MAX!).  */
640                     memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
641                     strcpy(lsp->fullname + sizeof tzdirslash, name);
642 
643                     /* Set doaccess if NAME contains a ".." file name
644                        component, as such a name could read a file outside
645                        the TZDIR virtual subtree.  */
646                     for (dot = name; (dot = strchr(dot, '.')); dot++)
647                       if ((dot == name || dot[-1] == '/') && dot[1] == '.'
648                           && (dot[2] == '/' || !dot[2])) {
649                         doaccess = true;
650                         break;
651                       }
652 
653                     name = lsp->fullname;
654           }
655           if (doaccess && (tzloadflags & TZLOAD_FROMENV)) {
656             /* Check for security violations and for devices whose mere
657                opening could have unwanted side effects.  Although these
658                checks are racy, they're better than nothing and there is
659                no portable way to fix the races.  */
660             if (access(name, R_OK) < 0)
661               return errno;
662 #if 0 /* handle with O_REGULAR instead */
663 #ifdef S_ISREG
664             {
665               struct stat st;
666               if (stat(name, &st) < 0)
667                 return errno;
668               if (!S_ISREG(st.st_mode))
669                 return EINVAL;
670             }
671 #endif
672 #endif
673           }
674           fid = open(name, (O_RDONLY | O_BINARY | O_CLOEXEC | O_CLOFORK
675                                 | O_IGNORE_CTTY | O_NOCTTY | O_REGULAR));
676           if (fid < 0)
677             return errno;
678 
679           nread = read(fid, up->buf, sizeof up->buf);
680           if (nread < (ssize_t)tzheadsize) {
681             int err = nread < 0 ? errno : EINVAL;
682             close(fid);
683             return err;
684           }
685           if (close(fid) < 0)
686             return errno;
687           for (stored = 4; stored <= 8; stored *= 2) {
688               char version = up->tzhead.tzh_version[0];
689               bool skip_datablock = stored == 4 && version;
690               int_fast32_t datablock_size;
691               int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
692               int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
693               int_fast64_t prevtr = -1;
694               int_fast32_t prevcorr = 0;
695               int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
696               int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
697               int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
698               int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
699               char const *p = up->buf + tzheadsize;
700               /* Although tzfile(5) currently requires typecnt to be nonzero,
701                  support future formats that may allow zero typecnt
702                  in files that have a TZ string and no transitions.  */
703               if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
704                        && 0 <= typecnt && typecnt < TZ_MAX_TYPES
705                        && 0 <= timecnt && timecnt < TZ_MAX_TIMES
706                        && 0 <= charcnt && charcnt < TZ_MAX_CHARS
707                        && 0 <= ttisstdcnt && ttisstdcnt < TZ_MAX_TYPES
708                        && 0 <= ttisutcnt && ttisutcnt < TZ_MAX_TYPES))
709                 return EINVAL;
710               datablock_size
711                         = (timecnt * stored                 /* ats */
712                            + timecnt              /* types */
713                            + typecnt * 6                    /* ttinfos */
714                            + charcnt              /* chars */
715                            + leapcnt * (stored + 4)         /* lsinfos */
716                            + ttisstdcnt           /* ttisstds */
717                            + ttisutcnt);                    /* ttisuts */
718               if (nread < (ssize_t)(tzheadsize + datablock_size))
719                 return EINVAL;
720               if (skip_datablock)
721                     p += datablock_size;
722               else {
723                     if (! ((ttisstdcnt == typecnt || ttisstdcnt == 0)
724                            && (ttisutcnt == typecnt || ttisutcnt == 0)))
725                       return EINVAL;
726 
727                     sp->leapcnt = (int)leapcnt;
728                     sp->timecnt = (int)timecnt;
729                     sp->typecnt = (int)typecnt;
730                     sp->charcnt = (int)charcnt;
731 
732                     /* Read transitions, discarding those out of time_t range.
733                        But pretend the last transition before TIME_T_MIN
734                        occurred at TIME_T_MIN.  */
735                     timecnt = 0;
736                     for (i = 0; i < sp->timecnt; ++i) {
737                               int_fast64_t at
738                                 = stored == 4 ? detzcode(p) : detzcode64(p);
739                               sp->types[i] = at <= TIME_T_MAX;
740                               if (sp->types[i]) {
741                                 time_t attime
742                                   = ((TYPE_SIGNED(time_t) ? at < TIME_T_MIN : at < 0)
743                                      ? TIME_T_MIN : (time_t)at);
744                                 if (timecnt && attime <= sp->ats[timecnt - 1]) {
745                                   if (attime < sp->ats[timecnt - 1])
746                                     return EINVAL;
747                                   sp->types[i - 1] = 0;
748                                   timecnt--;
749                                 }
750                                 sp->ats[timecnt++] = attime;
751                               }
752                               p += stored;
753                     }
754 
755                     timecnt = 0;
756                     for (i = 0; i < sp->timecnt; ++i) {
757                               unsigned char typ = *p++;
758                               if (sp->typecnt <= typ)
759                                 return EINVAL;
760                               if (sp->types[i])
761                                         sp->types[timecnt++] = typ;
762                     }
763                     sp->timecnt = (int)timecnt;
764                     for (i = 0; i < sp->typecnt; ++i) {
765                               register struct ttinfo *      ttisp;
766                               unsigned char isdst, desigidx;
767 
768                               ttisp = &sp->ttis[i];
769                               ttisp->tt_utoff = (int_least32_t)detzcode(p);
770                               p += 4;
771                               isdst = *p++;
772                               if (! (isdst < 2))
773                                 return EINVAL;
774                               ttisp->tt_isdst = isdst;
775                               desigidx = *p++;
776                               if (! (desigidx < sp->charcnt))
777                                 return EINVAL;
778                               ttisp->tt_desigidx = desigidx;
779                     }
780                     for (i = 0; i < sp->charcnt; ++i)
781                               sp->chars[i] = *p++;
782                     /* Ensure '\0'-terminated, and make it safe to call
783                        ttunspecified later.  */
784                     memset(&sp->chars[i], 0, CHARS_EXTRA);
785 
786                     /* Read leap seconds, discarding those out of time_t range.  */
787                     leapcnt = 0;
788                     for (i = 0; i < sp->leapcnt; ++i) {
789                       int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
790                       int_fast32_t corr = detzcode(p + stored);
791                       p += stored + 4;
792 
793                       /* Leap seconds cannot occur before the Epoch,
794                          or out of order.  */
795                       if (tr <= prevtr)
796                         return EINVAL;
797 
798                       /* To avoid other botches in this code, each leap second's
799                          correction must differ from the previous one's by 1
800                          second or less, except that the first correction can be
801                          any value; these requirements are more generous than
802                          RFC 9636, to allow future RFC extensions.  */
803                       if (! (i == 0
804                                || (prevcorr < corr
805                                    ? corr == prevcorr + 1
806                                    : (corr == prevcorr
807                                         || corr == prevcorr - 1))))
808                         return EINVAL;
809                       prevtr = tr;
810                       prevcorr = corr;
811 
812                       if (tr <= TIME_T_MAX) {
813                         sp->lsis[leapcnt].ls_trans = (time_t)tr;
814                         sp->lsis[leapcnt].ls_corr = corr;
815                         leapcnt++;
816                       }
817                     }
818                     sp->leapcnt = (int)leapcnt;
819 
820                     for (i = 0; i < sp->typecnt; ++i) {
821                               register struct ttinfo *      ttisp;
822 
823                               ttisp = &sp->ttis[i];
824                               if (ttisstdcnt == 0)
825                                         ttisp->tt_ttisstd = false;
826                               else {
827                                         if (*p != true && *p != false)
828                                           return EINVAL;
829                                         ttisp->tt_ttisstd = *p++;
830                               }
831                     }
832                     for (i = 0; i < sp->typecnt; ++i) {
833                               register struct ttinfo *      ttisp;
834 
835                               ttisp = &sp->ttis[i];
836                               if (ttisutcnt == 0)
837                                         ttisp->tt_ttisut = false;
838                               else {
839                                         if (*p != true && *p != false)
840                                                             return EINVAL;
841                                         ttisp->tt_ttisut = *p++;
842                               }
843                     }
844               }
845 
846               nread -= p - up->buf;
847               memmove(up->buf, p, (size_t)nread);
848 
849               /* If this is an old file, we're done.  */
850               if (!version)
851                 break;
852           }
853           if ((tzloadflags & TZLOAD_TZSTRING) && nread > 2 &&
854                     up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
855                     sp->typecnt + 2 <= TZ_MAX_TYPES) {
856                               struct state        *ts = &lsp->u.st;
857 
858                               up->buf[nread - 1] = '\0';
859                               if (tzparse(&up->buf[1], ts, sp)) {
860 
861                                 /* Attempt to reuse existing abbreviations.
862                                    Without this, America/Anchorage would be right on
863                                    the edge after 2037 when TZ_MAX_CHARS is 50, as
864                                    sp->charcnt equals 40 (for LMT AST AWT APT AHST
865                                    AHDT YST AKDT AKST) and ts->charcnt equals 10
866                                    (for AKST AKDT).  Reusing means sp->charcnt can
867                                    stay 40 in this example.  */
868                                 int gotabbr = 0;
869                                 int charcnt = sp->charcnt;
870                                 for (i = 0; i < ts->typecnt; i++) {
871                                   char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
872                                   int j;
873                                   for (j = 0; j < charcnt; j++)
874                                     if (strcmp(sp->chars + j, tsabbr) == 0) {
875                                         ts->ttis[i].tt_desigidx = j;
876                                         gotabbr++;
877                                         break;
878                                     }
879                                   if (! (j < charcnt)) {
880                                     size_t tsabbrlen = strlen(tsabbr);
881                                     if (j + tsabbrlen < TZ_MAX_CHARS) {
882                                         strcpy(sp->chars + j, tsabbr);
883                                         charcnt = (int)(j + tsabbrlen + 1);
884                                         ts->ttis[i].tt_desigidx = j;
885                                         gotabbr++;
886                                     }
887                                   }
888                                 }
889                                 if (gotabbr == ts->typecnt) {
890                                   sp->charcnt = charcnt;
891 
892                                   /* Ignore any trailing, no-op transitions generated
893                                      by zic as they don't help here and can run afoul
894                                      of bugs in zic 2016j or earlier.  */
895                                   while (1 < sp->timecnt
896                                            && (sp->types[sp->timecnt - 1]
897                                                == sp->types[sp->timecnt - 2]))
898                                     sp->timecnt--;
899 
900                                   sp->goahead = ts->goahead;
901 
902                                   for (i = 0; i < ts->timecnt; i++) {
903                                     __time_t t = ts->ats[i];
904                                     if (increment_overflow_time(&t, leapcorr(sp, t))
905                                           || (0 < sp->timecnt
906                                               && t <= sp->ats[sp->timecnt - 1]))
907                                         continue;
908                                     if (TZ_MAX_TIMES <= sp->timecnt) {
909                                         sp->goahead = false;
910                                         break;
911                                     }
912                                     sp->ats[sp->timecnt] = t;
913                                     sp->types[sp->timecnt] = (sp->typecnt
914                                                                       + ts->types[i]);
915                                     sp->timecnt++;
916                                   }
917                                   for (i = 0; i < ts->typecnt; i++)
918                                     sp->ttis[sp->typecnt++] = ts->ttis[i];
919                                 }
920                               }
921           }
922           if (sp->typecnt == 0)
923             return EINVAL;
924 
925           return 0;
926 }
927 
928 /* Load tz data from the file named NAME into *SP.  Respect TZLOADFLAGS.
929    Return 0 on success, an errno value on failure.  */
930 static int
tzload(char const * name,struct state * sp,char tzloadflags)931 tzload(char const *name, struct state *sp, char tzloadflags)
932 {
933 #ifdef ALL_STATE
934   union local_storage *lsp = malloc(sizeof *lsp);
935   if (!lsp) {
936     return /*CONSTCOND*/HAVE_MALLOC_ERRNO ? errno : ENOMEM;
937   } else {
938     int err = tzloadbody(name, sp, tzloadflags, lsp);
939     free(lsp);
940     return err;
941   }
942 #else
943   union local_storage ls;
944   return tzloadbody(name, sp, tzloadflags, &ls);
945 #endif
946 }
947 
948 static const int    mon_lengths[2][MONSPERYEAR] = {
949           { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
950           { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
951 };
952 
953 static const int    year_lengths[2] = {
954           DAYSPERNYEAR, DAYSPERLYEAR
955 };
956 
957 /* Is C an ASCII digit?  */
958 static bool
is_digit(char c)959 is_digit(char c)
960 {
961   return '0' <= c && c <= '9';
962 }
963 
964 /*
965 ** Given a pointer into a timezone string, scan until a character that is not
966 ** a valid character in a time zone abbreviation is found.
967 ** Return a pointer to that character.
968 */
969 
970 ATTRIBUTE_PURE_114833 static const char *
getzname(register const char * strp)971 getzname(register const char *strp)
972 {
973           register char       c;
974 
975           while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
976                     c != '+')
977                               ++strp;
978           return strp;
979 }
980 
981 /*
982 ** Given a pointer into an extended timezone string, scan until the ending
983 ** delimiter of the time zone abbreviation is located.
984 ** Return a pointer to the delimiter.
985 **
986 ** As with getzname above, the legal character set is actually quite
987 ** restricted, with other characters producing undefined results.
988 ** We don't do any checking here; checking is done later in common-case code.
989 */
990 
991 ATTRIBUTE_PURE_114833 static const char *
getqzname(register const char * strp,const int delim)992 getqzname(register const char *strp, const int delim)
993 {
994           register int        c;
995 
996           while ((c = *strp) != '\0' && c != delim)
997                     ++strp;
998           return strp;
999 }
1000 
1001 /*
1002 ** Given a pointer into a timezone string, extract a number from that string.
1003 ** Check that the number is within a specified range; if it is not, return
1004 ** NULL.
1005 ** Otherwise, return a pointer to the first character not part of the number.
1006 */
1007 
1008 static const char *
getnum(register const char * strp,int * const nump,const int min,const int max)1009 getnum(register const char *strp, int *const nump, const int min, const int max)
1010 {
1011           register char       c;
1012           register int        num;
1013 
1014           if (strp == NULL || !is_digit(c = *strp)) {
1015                     errno = EINVAL;
1016                     return NULL;
1017           }
1018           num = 0;
1019           do {
1020                     num = num * 10 + (c - '0');
1021                     if (num > max) {
1022                               errno = EOVERFLOW;
1023                               return NULL;        /* illegal value */
1024                     }
1025                     c = *++strp;
1026           } while (is_digit(c));
1027           if (num < min) {
1028                     errno = EINVAL;
1029                     return NULL;                  /* illegal value */
1030           }
1031           *nump = num;
1032           return strp;
1033 }
1034 
1035 /*
1036 ** Given a pointer into a timezone string, extract a number of seconds,
1037 ** in hh[:mm[:ss]] form, from the string.
1038 ** If any error occurs, return NULL.
1039 ** Otherwise, return a pointer to the first character not part of the number
1040 ** of seconds.
1041 */
1042 
1043 static const char *
getsecs(register const char * strp,int_fast32_t * const secsp)1044 getsecs(register const char *strp, int_fast32_t *const secsp)
1045 {
1046           int       num;
1047           int_fast32_t secsperhour = SECSPERHOUR;
1048 
1049           /*
1050           ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-POSIX rules like
1051           ** "M10.4.6/26", which does not conform to POSIX,
1052           ** but which specifies the equivalent of
1053           ** "02:00 on the first Sunday on or after 23 Oct".
1054           */
1055           strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
1056           if (strp == NULL)
1057                     return NULL;
1058           *secsp = num * secsperhour;
1059           if (*strp == ':') {
1060                     ++strp;
1061                     strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
1062                     if (strp == NULL)
1063                               return NULL;
1064                     *secsp += num * SECSPERMIN;
1065                     if (*strp == ':') {
1066                               ++strp;
1067                               /* 'SECSPERMIN' allows for leap seconds.  */
1068                               strp = getnum(strp, &num, 0, SECSPERMIN);
1069                               if (strp == NULL)
1070                                         return NULL;
1071                               *secsp += num;
1072                     }
1073           }
1074           return strp;
1075 }
1076 
1077 /*
1078 ** Given a pointer into a timezone string, extract an offset, in
1079 ** [+-]hh[:mm[:ss]] form, from the string.
1080 ** If any error occurs, return NULL.
1081 ** Otherwise, return a pointer to the first character not part of the time.
1082 */
1083 
1084 static const char *
getoffset(register const char * strp,int_fast32_t * const offsetp)1085 getoffset(register const char *strp, int_fast32_t *const offsetp)
1086 {
1087           register bool neg = false;
1088 
1089           if (*strp == '-') {
1090                     neg = true;
1091                     ++strp;
1092           } else if (*strp == '+')
1093                     ++strp;
1094           strp = getsecs(strp, offsetp);
1095           if (strp == NULL)
1096                     return NULL;                  /* illegal time */
1097           if (neg)
1098                     *offsetp = -*offsetp;
1099           return strp;
1100 }
1101 
1102 /*
1103 ** Given a pointer into a timezone string, extract a rule in the form
1104 ** date[/time]. See POSIX Base Definitions section 8.3 variable TZ
1105 ** for the format of "date" and "time".
1106 ** If a valid rule is not found, return NULL.
1107 ** Otherwise, return a pointer to the first character not part of the rule.
1108 */
1109 
1110 static const char *
getrule(const char * strp,register struct rule * const rulep)1111 getrule(const char *strp, register struct rule *const rulep)
1112 {
1113           if (*strp == 'J') {
1114                     /*
1115                     ** Julian day.
1116                     */
1117                     rulep->r_type = JULIAN_DAY;
1118                     ++strp;
1119                     strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1120           } else if (*strp == 'M') {
1121                     /*
1122                     ** Month, week, day.
1123                     */
1124                     rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
1125                     ++strp;
1126                     strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1127                     if (strp == NULL)
1128                               return NULL;
1129                     if (*strp++ != '.')
1130                               return NULL;
1131                     strp = getnum(strp, &rulep->r_week, 1, 5);
1132                     if (strp == NULL)
1133                               return NULL;
1134                     if (*strp++ != '.')
1135                               return NULL;
1136                     strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
1137           } else if (is_digit(*strp)) {
1138                     /*
1139                     ** Day of year.
1140                     */
1141                     rulep->r_type = DAY_OF_YEAR;
1142                     strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
1143           } else    return NULL;                  /* invalid format */
1144           if (strp == NULL)
1145                     return NULL;
1146           if (*strp == '/') {
1147                     /*
1148                     ** Time specified.
1149                     */
1150                     ++strp;
1151                     strp = getoffset(strp, &rulep->r_time);
1152           } else    rulep->r_time = 2 * SECSPERHOUR;        /* default = 2:00:00 */
1153           return strp;
1154 }
1155 
1156 /*
1157 ** Given a year, a rule, and the offset from UT at the time that rule takes
1158 ** effect, calculate the year-relative time that rule takes effect.
1159 */
1160 
1161 static int_fast32_t
transtime(const int year,register const struct rule * const rulep,const int_fast32_t offset)1162 transtime(const int year, register const struct rule *const rulep,
1163             const int_fast32_t offset)
1164 {
1165           register bool       leapyear;
1166           register int_fast32_t value;
1167           register int        i;
1168           int                 d, m1, yy0, yy1, yy2, dow;
1169 
1170           leapyear = isleap(year);
1171           switch (rulep->r_type) {
1172 
1173           case JULIAN_DAY:
1174                     /*
1175                     ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1176                     ** years.
1177                     ** In non-leap years, or if the day number is 59 or less, just
1178                     ** add SECSPERDAY times the day number-1 to the time of
1179                     ** January 1, midnight, to get the day.
1180                     */
1181                     value = (rulep->r_day - 1) * SECSPERDAY;
1182                     if (leapyear && rulep->r_day >= 60)
1183                               value += SECSPERDAY;
1184                     break;
1185 
1186           case DAY_OF_YEAR:
1187                     /*
1188                     ** n - day of year.
1189                     ** Just add SECSPERDAY times the day number to the time of
1190                     ** January 1, midnight, to get the day.
1191                     */
1192                     value = rulep->r_day * SECSPERDAY;
1193                     break;
1194 
1195           case MONTH_NTH_DAY_OF_WEEK:
1196                     /*
1197                     ** Mm.n.d - nth "dth day" of month m.
1198                     */
1199 
1200                     /*
1201                     ** Use Zeller's Congruence to get day-of-week of first day of
1202                     ** month.
1203                     */
1204                     m1 = (rulep->r_mon + 9) % 12 + 1;
1205                     yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1206                     yy1 = yy0 / 100;
1207                     yy2 = yy0 % 100;
1208                     dow = ((26 * m1 - 2) / 10 +
1209                               1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1210                     if (dow < 0)
1211                               dow += DAYSPERWEEK;
1212 
1213                     /*
1214                     ** "dow" is the day-of-week of the first day of the month. Get
1215                     ** the day-of-month (zero-origin) of the first "dow" day of the
1216                     ** month.
1217                     */
1218                     d = rulep->r_day - dow;
1219                     if (d < 0)
1220                               d += DAYSPERWEEK;
1221                     for (i = 1; i < rulep->r_week; ++i) {
1222                               if (d + DAYSPERWEEK >=
1223                                         mon_lengths[leapyear][rulep->r_mon - 1])
1224                                                   break;
1225                               d += DAYSPERWEEK;
1226                     }
1227 
1228                     /*
1229                     ** "d" is the day-of-month (zero-origin) of the day we want.
1230                     */
1231                     value = d * SECSPERDAY;
1232                     for (i = 0; i < rulep->r_mon - 1; ++i)
1233                               value += mon_lengths[leapyear][i] * SECSPERDAY;
1234                     break;
1235 
1236           default: unreachable();
1237           }
1238 
1239           /*
1240           ** "value" is the year-relative time of 00:00:00 UT on the day in
1241           ** question. To get the year-relative time of the specified local
1242           ** time on that day, add the transition time and the current offset
1243           ** from UT.
1244           */
1245           return value + rulep->r_time + offset;
1246 }
1247 
1248 /*
1249 ** Given a POSIX.1 proleptic TZ string, fill in the rule tables as
1250 ** appropriate.
1251 */
1252 
1253 static bool
tzparse(const char * name,struct state * sp,struct state const * basep)1254 tzparse(const char *name, struct state *sp, struct state const *basep)
1255 {
1256           const char *                            stdname;
1257           const char *                            dstname;
1258           int_fast32_t                            stdoffset;
1259           int_fast32_t                            dstoffset;
1260           register char *                         cp;
1261           register bool                           load_ok;
1262           ptrdiff_t stdlen, dstlen, charcnt;
1263           __time_t atlo = TIME_T_MIN, leaplo = TIME_T_MIN;
1264 
1265           dstname = NULL; /* XXX gcc */
1266           stdname = name;
1267           if (*name == '<') {
1268             name++;
1269             stdname = name;
1270             name = getqzname(name, '>');
1271             if (*name != '>')
1272               return false;
1273             stdlen = name - stdname;
1274             name++;
1275           } else {
1276             name = getzname(name);
1277             stdlen = name - stdname;
1278           }
1279           if (! (0 < stdlen && stdlen <= TZNAME_MAXIMUM))
1280             return false;
1281           name = getoffset(name, &stdoffset);
1282           if (name == NULL)
1283             return false;
1284           charcnt = stdlen + 1;
1285           if (basep) {
1286             if (0 < basep->timecnt)
1287               atlo = basep->ats[basep->timecnt - 1];
1288             load_ok = false;
1289             sp->leapcnt = basep->leapcnt;
1290             memcpy(sp->lsis, basep->lsis, sp->leapcnt * sizeof *sp->lsis);
1291           } else {
1292             load_ok = tzload(TZDEFRULES, sp, 0) == 0;
1293             if (!load_ok)
1294               sp->leapcnt = 0;          /* So, we're off a little.  */
1295           }
1296           if (0 < sp->leapcnt)
1297             leaplo = sp->lsis[sp->leapcnt - 1].ls_trans;
1298           sp->goback = sp->goahead = false;
1299           if (*name != '\0') {
1300                     if (*name == '<') {
1301                               dstname = ++name;
1302                               name = getqzname(name, '>');
1303                               if (*name != '>')
1304                                 return false;
1305                               dstlen = name - dstname;
1306                               name++;
1307                     } else {
1308                               dstname = name;
1309                               name = getzname(name);
1310                               dstlen = name - dstname; /* length of DST abbr. */
1311                     }
1312                     if (! (0 < dstlen && dstlen <= TZNAME_MAXIMUM))
1313                       return false;
1314                     charcnt += dstlen + 1;
1315                     if (*name != '\0' && *name != ',' && *name != ';') {
1316                               name = getoffset(name, &dstoffset);
1317                               if (name == NULL)
1318                                 return false;
1319                     } else    dstoffset = stdoffset - SECSPERHOUR;
1320                     if (*name == '\0' && !load_ok)
1321                               name = TZDEFRULESTRING;
1322                     if (*name == ',' || *name == ';') {
1323                               struct rule         start;
1324                               struct rule         end;
1325                               register int        year;
1326                               register int        timecnt;
1327                               __time_t  janfirst;
1328                               int_fast32_t janoffset = 0;
1329                               int yearbeg, yearlim;
1330 
1331                               ++name;
1332                               if ((name = getrule(name, &start)) == NULL)
1333                                 return false;
1334                               if (*name++ != ',')
1335                                 return false;
1336                               if ((name = getrule(name, &end)) == NULL)
1337                                 return false;
1338                               if (*name != '\0')
1339                                 return false;
1340                               sp->typecnt = 2;    /* standard time and DST */
1341                               /*
1342                               ** Two transitions per year, from EPOCH_YEAR forward.
1343                               */
1344                               init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1345                               init_ttinfo(&sp->ttis[1], -dstoffset, true,
1346                                   (int)(stdlen + 1));
1347                               timecnt = 0;
1348                               janfirst = 0;
1349                               yearbeg = EPOCH_YEAR;
1350 
1351                               do {
1352                                 int_fast32_t yearsecs
1353                                   = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1354                                 __time_t janfirst1 = janfirst;
1355                                 yearbeg--;
1356                                 if (increment_overflow_time(&janfirst1, -yearsecs)) {
1357                                   janoffset = -yearsecs;
1358                                   break;
1359                                 }
1360                                 janfirst = janfirst1;
1361                               } while (atlo < janfirst
1362                                          && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1363 
1364                               for (;;) {
1365                                 int_fast32_t yearsecs
1366                                   = year_lengths[isleap(yearbeg)] * SECSPERDAY;
1367                                 int yearbeg1 = yearbeg;
1368                                 __time_t janfirst1 = janfirst;
1369                                 if (increment_overflow_time(&janfirst1, yearsecs)
1370                                     || increment_overflow(&yearbeg1, 1)
1371                                     || atlo <= janfirst1)
1372                                   break;
1373                                 yearbeg = yearbeg1;
1374                                 janfirst = janfirst1;
1375                               }
1376 
1377                               yearlim = yearbeg;
1378                               if (increment_overflow(&yearlim, years_of_observations))
1379                                 yearlim = INT_MAX;
1380                               for (year = yearbeg; year < yearlim; year++) {
1381                                         int_fast32_t
1382                                           starttime = transtime(year, &start, stdoffset),
1383                                           endtime = transtime(year, &end, dstoffset);
1384                                         int_fast32_t
1385                                           yearsecs = (year_lengths[isleap(year)]
1386                                                         * SECSPERDAY);
1387                                         bool reversed = endtime < starttime;
1388                                         if (reversed) {
1389                                                   int_fast32_t swap = starttime;
1390                                                   starttime = endtime;
1391                                                   endtime = swap;
1392                                         }
1393                                         if (reversed
1394                                             || (starttime < endtime
1395                                                   && endtime - starttime < yearsecs)) {
1396                                                   if (TZ_MAX_TIMES - 2 < timecnt)
1397                                                             break;
1398                                                   sp->ats[timecnt] = janfirst;
1399                                                   if (! increment_overflow_time
1400                                                       (&sp->ats[timecnt],
1401                                                        janoffset + starttime)
1402                                                       && atlo <= sp->ats[timecnt])
1403                                                     sp->types[timecnt++] = !reversed;
1404                                                   sp->ats[timecnt] = janfirst;
1405                                                   if (! increment_overflow_time
1406                                                       (&sp->ats[timecnt],
1407                                                        janoffset + endtime)
1408                                                       && atlo <= sp->ats[timecnt]) {
1409                                                     sp->types[timecnt++] = reversed;
1410                                                   }
1411                                         }
1412                                         if (endtime < leaplo) {
1413                                           yearlim = year;
1414                                           if (increment_overflow(&yearlim,
1415                                                                        years_of_observations))
1416                                             yearlim = INT_MAX;
1417                                         }
1418                                         if (increment_overflow_time
1419                                             (&janfirst, janoffset + yearsecs))
1420                                                   break;
1421                                         janoffset = 0;
1422                               }
1423                               sp->timecnt = timecnt;
1424                               if (! timecnt) {
1425                                         sp->ttis[0] = sp->ttis[1];
1426                                         sp->typecnt = 1;    /* Perpetual DST.  */
1427                               } else if (years_of_observations <= year - yearbeg)
1428                                         sp->goback = sp->goahead = true;
1429                     } else {
1430                               register int_fast32_t         theirstdoffset;
1431                               register int_fast32_t         theirdstoffset;
1432                               register int_fast32_t         theiroffset;
1433                               register bool                 isdst;
1434                               register int                  i;
1435                               register int                  j;
1436 
1437                               if (*name != '\0')
1438                                 return false;
1439                               /*
1440                               ** Initial values of theirstdoffset and theirdstoffset.
1441                               */
1442                               theirstdoffset = 0;
1443                               for (i = 0; i < sp->timecnt; ++i) {
1444                                         j = sp->types[i];
1445                                         if (!sp->ttis[j].tt_isdst) {
1446                                                   theirstdoffset =
1447                                                             - sp->ttis[j].tt_utoff;
1448                                                   break;
1449                                         }
1450                               }
1451                               theirdstoffset = 0;
1452                               for (i = 0; i < sp->timecnt; ++i) {
1453                                         j = sp->types[i];
1454                                         if (sp->ttis[j].tt_isdst) {
1455                                                   theirdstoffset =
1456                                                             - sp->ttis[j].tt_utoff;
1457                                                   break;
1458                                         }
1459                               }
1460                               /*
1461                               ** Initially we're assumed to be in standard time.
1462                               */
1463                               isdst = false;
1464                               /*
1465                               ** Now juggle transition times and types
1466                               ** tracking offsets as you do.
1467                               */
1468                               for (i = 0; i < sp->timecnt; ++i) {
1469                                         j = sp->types[i];
1470                                         sp->types[i] = sp->ttis[j].tt_isdst;
1471                                         if (sp->ttis[j].tt_ttisut) {
1472                                                   /* No adjustment to transition time */
1473                                         } else {
1474                                                   /*
1475                                                   ** If daylight saving time is in
1476                                                   ** effect, and the transition time was
1477                                                   ** not specified as standard time, add
1478                                                   ** the daylight saving time offset to
1479                                                   ** the transition time; otherwise, add
1480                                                   ** the standard time offset to the
1481                                                   ** transition time.
1482                                                   */
1483                                                   /*
1484                                                   ** Transitions from DST to DDST
1485                                                   ** will effectively disappear since
1486                                                   ** proleptic TZ strings have only one
1487                                                   ** DST offset.
1488                                                   */
1489                                                   if (isdst && !sp->ttis[j].tt_ttisstd) {
1490                                                             sp->ats[i] += (time_t)
1491                                                                 (dstoffset - theirdstoffset);
1492                                                   } else {
1493                                                             sp->ats[i] += (time_t)
1494                                                                 (stdoffset - theirstdoffset);
1495                                                   }
1496                                         }
1497                                         theiroffset = -sp->ttis[j].tt_utoff;
1498                                         if (sp->ttis[j].tt_isdst)
1499                                                   theirdstoffset = theiroffset;
1500                                         else      theirstdoffset = theiroffset;
1501                               }
1502                               /*
1503                               ** Finally, fill in ttis.
1504                               */
1505                               init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1506                               init_ttinfo(&sp->ttis[1], -dstoffset, true,
1507                                   (int)(stdlen + 1));
1508                               sp->typecnt = 2;
1509                     }
1510           } else {
1511                     dstlen = 0;
1512                     sp->typecnt = 1;              /* only standard time */
1513                     sp->timecnt = 0;
1514                     init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1515                     init_ttinfo(&sp->ttis[1], 0, false, 0);
1516           }
1517           sp->charcnt = (int)charcnt;
1518           cp = sp->chars;
1519           memcpy(cp, stdname, stdlen);
1520           cp += stdlen;
1521           *cp++ = '\0';
1522           if (dstlen != 0) {
1523                     (void) memcpy(cp, dstname, dstlen);
1524                     *(cp + dstlen) = '\0';
1525           }
1526           return true;
1527 }
1528 
1529 static void
gmtload(struct state * const sp)1530 gmtload(struct state *const sp)
1531 {
1532           if (tzload(etc_utc, sp, TZLOAD_TZSTRING) != 0)
1533             (void)tzparse("UTC0", sp, NULL);
1534 }
1535 
1536 #if !USE_TIMEX_T || !defined TM_GMTOFF
1537 
1538 /* Initialize *SP to a value appropriate for the TZ setting NAME.
1539    Respect TZLOADFLAGS.
1540    Return 0 on success, an errno value on failure.  */
1541 static int
zoneinit(struct state * sp,char const * name,char tzloadflags)1542 zoneinit(struct state *sp, char const *name, char tzloadflags)
1543 {
1544   if (name && ! name[0]) {
1545     /*
1546     ** User wants it fast rather than right.
1547     */
1548     sp->leapcnt = 0;                    /* so, we're off a little */
1549     sp->timecnt = 0;
1550     sp->typecnt = 1;
1551     sp->charcnt = 0;
1552     sp->goback = sp->goahead = false;
1553     init_ttinfo(&sp->ttis[0], 0, false, 0);
1554     strcpy(sp->chars, utc);
1555     return 0;
1556   } else {
1557     int err = tzload(name, sp, tzloadflags);
1558     if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL))
1559       err = 0;
1560     if (err == 0)
1561       err = scrub_abbrs(sp);
1562     return err;
1563   }
1564 }
1565 
1566 static void
tzsetlcl(char const * name)1567 tzsetlcl(char const *name)
1568 {
1569   struct state *sp = __lclptr;
1570   int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
1571   if (lcl < 0
1572       ? lcl_is_set < 0
1573       : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
1574     return;
1575 
1576 # ifndef ALL_STATE
1577   if (! sp)
1578     __lclptr = sp = malloc(sizeof *__lclptr);
1579 # endif
1580   if (sp) {
1581     if (zoneinit(sp, name, TZLOAD_FROMENV | TZLOAD_TZSTRING) != 0) {
1582       zoneinit(sp, "", 0);
1583       strcpy(sp->chars, UNSPEC);
1584     }
1585     if (0 < lcl)
1586       strcpy(lcl_TZname, name);
1587   }
1588   settzname();
1589   lcl_is_set = lcl;
1590 }
1591 #endif
1592 
1593 #if !USE_TIMEX_T
1594 void
tzset(void)1595 tzset(void)
1596 {
1597   if (lock() != 0)
1598     return;
1599   tzset_unlocked();
1600   unlock();
1601 }
1602 
1603 #ifdef STD_INSPIRED
1604 void
tzsetwall(void)1605 tzsetwall(void)
1606 {
1607           if (lock() != 0)
1608                     return;
1609           tzsetlcl(NULL);
1610           unlock();
1611 }
1612 #endif
1613 
1614 void
tzset_unlocked(void)1615 tzset_unlocked(void)
1616 {
1617           tzsetlcl(getenv("TZ"));
1618 }
1619 #endif
1620 
1621 static void
gmtcheck(void)1622 gmtcheck(void)
1623 {
1624   static bool gmt_is_set;
1625   if (lock() != 0)
1626     return;
1627   if (! gmt_is_set) {
1628 #ifdef ALL_STATE
1629     gmtptr = malloc(sizeof *gmtptr);
1630 #endif
1631     if (gmtptr)
1632       gmtload(gmtptr);
1633     gmt_is_set = true;
1634   }
1635   unlock();
1636 }
1637 
1638 #if NETBSD_INSPIRED && !USE_TIMEX_T
1639 
1640 timezone_t
tzalloc(char const * name)1641 tzalloc(char const *name)
1642 {
1643   timezone_t sp = malloc(sizeof *sp);
1644   if (sp) {
1645     int err = zoneinit(sp, name, TZLOAD_TZSTRING);
1646     if (err != 0) {
1647       free(sp);
1648       errno = err;
1649       return NULL;
1650     }
1651   } else if (/*CONSTCOND*/!HAVE_MALLOC_ERRNO)
1652     /*NOTREACHED*/
1653     errno = ENOMEM;
1654   return sp;
1655 }
1656 
1657 void
tzfree(timezone_t sp)1658 tzfree(timezone_t sp)
1659 {
1660   free(sp);
1661 }
1662 
1663 /*
1664 ** NetBSD 6.1.4 has ctime_rz, but omit it because C23 deprecates ctime and
1665 ** POSIX.1-2024 removes ctime_r.  Both have potential security problems that
1666 ** ctime_rz would share.  Callers can instead use localtime_rz + strftime.
1667 **
1668 ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1669 ** in zones with three or more time zone abbreviations.
1670 ** Callers can instead use localtime_rz + strftime.
1671 */
1672 
1673 #endif
1674 
1675 #if !USE_TIMEX_T || !defined TM_GMTOFF
1676 
1677 /*
1678 ** The easy way to behave "as if no library function calls" localtime
1679 ** is to not call it, so we drop its guts into "localsub", which can be
1680 ** freely called. (And no, the PANS doesn't require the above behavior,
1681 ** but it *is* desirable.)
1682 **
1683 ** If successful and SETNAME is nonzero,
1684 ** set the applicable parts of tzname, timezone and altzone;
1685 ** however, it's OK to omit this step for proleptic TZ strings
1686 ** since in that case tzset should have already done this step correctly.
1687 ** SETNAME's type is int_fast32_t for compatibility with gmtsub,
1688 ** but it is actually a boolean and its value should be 0 or 1.
1689 */
1690 
1691 /*ARGSUSED*/
1692 static struct tm *
localsub(struct state const * sp,time_t const * timep,int_fast32_t setname,struct tm * const tmp)1693 localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
1694            struct tm *const tmp)
1695 {
1696           register const struct ttinfo *          ttisp;
1697           register int                            i;
1698           register struct tm *                    result;
1699           const time_t                            t = *timep;
1700 
1701           if (sp == NULL) {
1702             /* Don't bother to set tzname etc.; tzset has already done it.  */
1703             return gmtsub(gmtptr, timep, 0, tmp);
1704           }
1705           if ((sp->goback && t < sp->ats[0]) ||
1706                     (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1707                               time_t newt;
1708                               register __time_t   seconds;
1709                               register time_t               years;
1710 
1711                               if (t < sp->ats[0])
1712                                         seconds = sp->ats[0] - t;
1713                               else      seconds = t - sp->ats[sp->timecnt - 1];
1714                               --seconds;
1715 
1716                               /* Beware integer overflow, as SECONDS might
1717                                  be close to the maximum time_t.  */
1718                               years = (time_t)(seconds / SECSPERREPEAT
1719                                   * YEARSPERREPEAT);
1720                               seconds = (time_t)(years * AVGSECSPERYEAR);
1721                               years += YEARSPERREPEAT;
1722                               if (t < sp->ats[0])
1723                                 newt = (time_t)(t + seconds + SECSPERREPEAT);
1724                               else
1725                                 newt = (time_t)(t - seconds - SECSPERREPEAT);
1726 
1727                               if (newt < sp->ats[0] ||
1728                                         newt > sp->ats[sp->timecnt - 1]) {
1729                                         errno = EINVAL;
1730                                         return NULL;        /* "cannot happen" */
1731                               }
1732                               result = localsub(sp, &newt, setname, tmp);
1733                               if (result) {
1734 # if defined ckd_add && defined ckd_sub
1735                                         if (t < sp->ats[0]
1736                                             ? ckd_sub(&result->tm_year,
1737                                                         result->tm_year, years)
1738                                             : ckd_add(&result->tm_year,
1739                                                         result->tm_year, years))
1740                                           return NULL;
1741 # else
1742                                         register int_fast64_t newy;
1743 
1744                                         newy = result->tm_year;
1745                                         if (t < sp->ats[0])
1746                                                   newy -= years;
1747                                         else      newy += years;
1748                                         if (! (INT_MIN <= newy && newy <= INT_MAX)) {
1749                                                   errno = EOVERFLOW;
1750                                                   return NULL;
1751                                         }
1752                                         result->tm_year = (int)newy;
1753 # endif
1754                               }
1755                               return result;
1756           }
1757           if (sp->timecnt == 0 || t < sp->ats[0]) {
1758                     i = 0;
1759           } else {
1760                     register int        lo = 1;
1761                     register int        hi = sp->timecnt;
1762 
1763                     while (lo < hi) {
1764                               register int        mid = (lo + hi) / 2;
1765 
1766                               if (t < sp->ats[mid])
1767                                         hi = mid;
1768                               else      lo = mid + 1;
1769                     }
1770                     i = sp->types[lo - 1];
1771           }
1772           ttisp = &sp->ttis[i];
1773           /*
1774           ** To get (wrong) behavior that's compatible with System V Release 2.0
1775           ** you'd replace the statement below with
1776           **        t += ttisp->tt_utoff;
1777           **        timesub(&t, 0L, sp, tmp);
1778           */
1779           result = timesub(&t, ttisp->tt_utoff, sp, tmp);
1780           if (result) {
1781             result->tm_isdst = ttisp->tt_isdst;
1782 # ifdef TM_ZONE
1783             result->TM_ZONE = UNCONST(&sp->chars[ttisp->tt_desigidx]);
1784 # endif
1785             if (setname)
1786               update_tzname_etc(sp, ttisp);
1787           }
1788           return result;
1789 }
1790 #endif
1791 
1792 #if !USE_TIMEX_T
1793 
1794 # if NETBSD_INSPIRED
1795 struct tm *
localtime_rz(struct state * __restrict sp,time_t const * __restrict timep,struct tm * __restrict tmp)1796 localtime_rz(struct state *__restrict sp, time_t const *__restrict timep,
1797           struct tm *__restrict tmp)
1798 {
1799   return localsub(sp, timep, 0, tmp);
1800 }
1801 # endif
1802 
1803 static struct tm *
localtime_tzset(time_t const * timep,struct tm * tmp,bool setname)1804 localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
1805 {
1806   int err = lock();
1807   if (err) {
1808     errno = err;
1809     return NULL;
1810   }
1811   if (setname || !lcl_is_set)
1812     tzset_unlocked();
1813   tmp = localsub(__lclptr, timep, setname, tmp);
1814   unlock();
1815   return tmp;
1816 }
1817 
1818 struct tm *
localtime(const time_t * timep)1819 localtime(const time_t *timep)
1820 {
1821 # if !SUPPORT_C89
1822   static struct tm tm;
1823 # endif
1824   return localtime_tzset(timep, &tm, true);
1825 }
1826 
1827 struct tm *
localtime_r(const time_t * __restrict timep,struct tm * __restrict tmp)1828 localtime_r(const time_t *__restrict timep, struct tm *__restrict tmp)
1829 {
1830   return localtime_tzset(timep, tmp, false);
1831 }
1832 #endif
1833 
1834 /*
1835 ** gmtsub is to gmtime as localsub is to localtime.
1836 */
1837 
1838 static struct tm *
gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const * sp,time_t const * timep,int_fast32_t offset,struct tm * tmp)1839 gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const *sp, time_t const *timep,
1840        int_fast32_t offset, struct tm *tmp)
1841 {
1842           register struct tm *          result;
1843 
1844           result = timesub(timep, offset, gmtptr, tmp);
1845 #ifdef TM_ZONE
1846           /*
1847           ** Could get fancy here and deliver something such as
1848           ** "+xx" or "-xx" if offset is non-zero,
1849           ** but this is no time for a treasure hunt.
1850           */
1851           if (result)
1852                     result->TM_ZONE = UNCONST(offset ? wildabbr : gmtptr ?
1853                         gmtptr->chars : utc);
1854 #endif /* defined TM_ZONE */
1855           return result;
1856 }
1857 
1858 #if !USE_TIMEX_T
1859 
1860 /*
1861 * Re-entrant version of gmtime.
1862 */
1863 
1864 struct tm *
gmtime_r(time_t const * __restrict timep,struct tm * __restrict tmp)1865 gmtime_r(time_t const *__restrict timep, struct tm *__restrict tmp)
1866 {
1867   gmtcheck();
1868   return gmtsub(NULL, timep, 0, tmp);
1869 }
1870 
1871 struct tm *
gmtime(const time_t * timep)1872 gmtime(const time_t *timep)
1873 {
1874 # if !SUPPORT_C89
1875   static struct tm tm;
1876 # endif
1877   return gmtime_r(timep, &tm);
1878 }
1879 
1880 # if STD_INSPIRED
1881 
1882 /* This function is obsolescent and may disappear in future releases.
1883    Callers can instead use localtime_rz with a fixed-offset zone.  */
1884 
1885 struct tm *
offtime(const time_t * timep,long offset)1886 offtime(const time_t *timep, long offset)
1887 {
1888   gmtcheck();
1889 
1890 #  if !SUPPORT_C89
1891   static struct tm tm;
1892 #  endif
1893   return gmtsub(gmtptr, timep, (int_fast32_t)offset, &tm);
1894 }
1895 
1896 struct tm *
offtime_r(const time_t * timep,long offset,struct tm * tmp)1897 offtime_r(const time_t *timep, long offset, struct tm *tmp)
1898 {
1899           gmtcheck();
1900           return gmtsub(NULL, timep, (int_fast32_t)offset, tmp);
1901 }
1902 
1903 # endif
1904 #endif
1905 
1906 /*
1907 ** Return the number of leap years through the end of the given year
1908 ** where, to make the math easy, the answer for year zero is defined as zero.
1909 */
1910 
1911 static time_t
leaps_thru_end_of_nonneg(time_t y)1912 leaps_thru_end_of_nonneg(time_t y)
1913 {
1914   return y / 4 - y / 100 + y / 400;
1915 }
1916 
1917 static time_t
leaps_thru_end_of(time_t y)1918 leaps_thru_end_of(time_t y)
1919 {
1920   return (y < 0
1921             ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1922             : leaps_thru_end_of_nonneg(y));
1923 }
1924 
1925 static struct tm *
timesub(const time_t * timep,int_fast32_t offset,const struct state * sp,struct tm * tmp)1926 timesub(const time_t *timep, int_fast32_t offset,
1927           const struct state *sp, struct tm *tmp)
1928 {
1929           register const struct lsinfo *          lp;
1930           register time_t                         tdays;
1931           register const int *                    ip;
1932           register int_fast32_t                   corr;
1933           register int                            i;
1934           int_fast32_t idays, rem, dayoff, dayrem;
1935           time_t y;
1936 
1937           /* If less than SECSPERMIN, the number of seconds since the
1938              most recent positive leap second; otherwise, do not add 1
1939              to localtime tm_sec because of leap seconds.  */
1940           __time_t secs_since_posleap = SECSPERMIN;
1941 
1942           corr = 0;
1943           i = (sp == NULL) ? 0 : sp->leapcnt;
1944           while (--i >= 0) {
1945                     lp = &sp->lsis[i];
1946                     if (*timep >= lp->ls_trans) {
1947                               corr = lp->ls_corr;
1948                               if ((i == 0 ? 0 : lp[-1].ls_corr) < corr)
1949                                 secs_since_posleap = *timep - lp->ls_trans;
1950                               break;
1951                     }
1952           }
1953 
1954           /* Calculate the year, avoiding integer overflow even if
1955              time_t is unsigned.  */
1956           tdays = (time_t)(*timep / SECSPERDAY);
1957           rem = (int)(*timep % SECSPERDAY);
1958           rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
1959           dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
1960           rem %= SECSPERDAY;
1961           /* y = (EPOCH_YEAR
1962                     + floor((tdays + dayoff) / DAYSPERREPEAT) * YEARSPERREPEAT),
1963              sans overflow.  But calculate against 1570 (EPOCH_YEAR -
1964              YEARSPERREPEAT) instead of against 1970 so that things work
1965              for localtime values before 1970 when time_t is unsigned.  */
1966           dayrem = (int)(tdays % DAYSPERREPEAT);
1967           dayrem += dayoff % DAYSPERREPEAT;
1968           y = (time_t)(EPOCH_YEAR - YEARSPERREPEAT
1969                + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
1970                      - ((dayrem % DAYSPERREPEAT) < 0)
1971                      + tdays / DAYSPERREPEAT)
1972                     * YEARSPERREPEAT));
1973           /* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow.  */
1974           idays = (int)(tdays % DAYSPERREPEAT);
1975           idays += (dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT);
1976           idays %= DAYSPERREPEAT;
1977           /* Increase Y and decrease IDAYS until IDAYS is in range for Y.  */
1978           while (year_lengths[isleap(y)] <= idays) {
1979                     int_fast32_t tdelta = idays / DAYSPERLYEAR;
1980                     int_fast32_t ydelta = tdelta + !tdelta;
1981                     time_t newy = (time_t)(y + ydelta);
1982                     register int        leapdays;
1983                     leapdays = (int)(leaps_thru_end_of(newy - 1) -
1984                               leaps_thru_end_of(y - 1));
1985                     idays -= ydelta * DAYSPERNYEAR;
1986                     idays -= leapdays;
1987                     y = newy;
1988           }
1989 
1990 #ifdef ckd_add
1991           if (ckd_add(&tmp->tm_year, y, -TM_YEAR_BASE)) {
1992             errno = EOVERFLOW;
1993             return NULL;
1994           }
1995 #else
1996           if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) {
1997             int signed_y = (int)y;
1998             tmp->tm_year = signed_y - TM_YEAR_BASE;
1999           } else if ((!TYPE_SIGNED(time_t) || INT_MIN + TM_YEAR_BASE <= y)
2000                        && y - TM_YEAR_BASE <= INT_MAX)
2001             tmp->tm_year = (int)(y - TM_YEAR_BASE);
2002           else {
2003             errno = EOVERFLOW;
2004             return NULL;
2005           }
2006 #endif
2007           tmp->tm_yday = (int)idays;
2008           /*
2009           ** The "extra" mods below avoid overflow problems.
2010           */
2011           tmp->tm_wday = (int)(TM_WDAY_BASE
2012                               + ((tmp->tm_year % DAYSPERWEEK)
2013                                  * (DAYSPERNYEAR % DAYSPERWEEK))
2014                               + leaps_thru_end_of(y - 1)
2015                               - leaps_thru_end_of(TM_YEAR_BASE - 1)
2016                               + idays);
2017           tmp->tm_wday %= DAYSPERWEEK;
2018           if (tmp->tm_wday < 0)
2019                     tmp->tm_wday += DAYSPERWEEK;
2020           tmp->tm_hour = (int) (rem / SECSPERHOUR);
2021           rem %= SECSPERHOUR;
2022           tmp->tm_min = (int)(rem / SECSPERMIN);
2023           tmp->tm_sec = (int)(rem % SECSPERMIN);
2024 
2025           /* Use "... ??:??:60" at the end of the localtime minute containing
2026              the second just before the positive leap second.  */
2027           tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
2028 
2029           ip = mon_lengths[isleap(y)];
2030           for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
2031                     idays -= ip[tmp->tm_mon];
2032           tmp->tm_mday = (int)(idays + 1);
2033           tmp->tm_isdst = 0;
2034 #ifdef TM_GMTOFF
2035           tmp->TM_GMTOFF = offset;
2036 #endif /* defined TM_GMTOFF */
2037           return tmp;
2038 }
2039 
2040 /*
2041 ** Adapted from code provided by Robert Elz, who writes:
2042 **        The "best" way to do mktime I think is based on an idea of Bob
2043 **        Kridle's (so its said...) from a long time ago.
2044 **        It does a binary search of the time_t space. Since time_t's are
2045 **        just 32 bits, its a max of 32 iterations (even at 64 bits it
2046 **        would still be very reasonable).
2047 */
2048 
2049 #ifndef WRONG
2050 # define WRONG ((time_t)-1)
2051 #endif /* !defined WRONG */
2052 
2053 /*
2054 ** Normalize logic courtesy Paul Eggert.
2055 */
2056 
2057 static bool
increment_overflow(int * ip,int j)2058 increment_overflow(int *ip, int j)
2059 {
2060 #ifdef ckd_add
2061           return ckd_add(ip, *ip, j);
2062 #else
2063           register int const  i = *ip;
2064 
2065           /*
2066           ** If i >= 0 there can only be overflow if i + j > INT_MAX
2067           ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
2068           ** If i < 0 there can only be overflow if i + j < INT_MIN
2069           ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
2070           */
2071           if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
2072                     return true;
2073           *ip += j;
2074           return false;
2075 #endif
2076 }
2077 
2078 static bool
increment_overflow_time_iinntt(time_t * tp,iinntt j)2079 increment_overflow_time_iinntt(time_t *tp, iinntt j)
2080 {
2081 #ifdef ckd_add
2082   return ckd_add(tp, *tp, j);
2083 #else
2084   if (j < 0
2085       ? (TYPE_SIGNED(time_t) ? *tp < TIME_T_MIN - j : *tp <= -1 - j)
2086       : TIME_T_MAX - j < *tp)
2087     return true;
2088   *tp += j;
2089   return false;
2090 #endif
2091 }
2092 
2093 static bool
increment_overflow_time(__time_t * tp,int_fast32_t j)2094 increment_overflow_time(__time_t *tp, int_fast32_t j)
2095 {
2096 #ifdef ckd_add
2097           return ckd_add(tp, *tp, j);
2098 #else
2099           /*
2100           ** This is like
2101           ** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
2102           ** except that it does the right thing even if *tp + j would overflow.
2103           */
2104           if (! (j < 0
2105                  ? (TYPE_SIGNED(time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
2106                  : *tp <= TIME_T_MAX - j))
2107                     return true;
2108           *tp += j;
2109           return false;
2110 #endif
2111 }
2112 
2113 static int
tmcomp(register const struct tm * const atmp,register const struct tm * const btmp)2114 tmcomp(register const struct tm *const atmp,
2115        register const struct tm *const btmp)
2116 {
2117           register int        result;
2118 
2119           if (atmp->tm_year != btmp->tm_year)
2120                     return atmp->tm_year < btmp->tm_year ? -1 : 1;
2121           if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
2122                     (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
2123                     (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
2124                     (result = (atmp->tm_min - btmp->tm_min)) == 0)
2125                               result = atmp->tm_sec - btmp->tm_sec;
2126           return result;
2127 }
2128 
2129 /* Copy to *DEST from *SRC.  Copy only the members needed for mktime,
2130    as other members might not be initialized.  */
2131 static void
mktmcpy(struct tm * dest,struct tm const * src)2132 mktmcpy(struct tm *dest, struct tm const *src)
2133 {
2134   dest->tm_sec = src->tm_sec;
2135   dest->tm_min = src->tm_min;
2136   dest->tm_hour = src->tm_hour;
2137   dest->tm_mday = src->tm_mday;
2138   dest->tm_mon = src->tm_mon;
2139   dest->tm_year = src->tm_year;
2140   dest->tm_isdst = src->tm_isdst;
2141 #if defined TM_GMTOFF && ! UNINIT_TRAP
2142   dest->TM_GMTOFF = src->TM_GMTOFF;
2143 #endif
2144 }
2145 
2146 static time_t
time2sub(struct tm * const tmp,struct tm * (* funcp)(struct state const *,time_t const *,int_fast32_t,struct tm *),struct state const * sp,const int_fast32_t offset,bool * okayp,bool do_norm_secs)2147 time2sub(struct tm *const tmp,
2148            struct tm *(*funcp)(struct state const *, time_t const *,
2149                                    int_fast32_t, struct tm *),
2150            struct state const *sp,
2151            const int_fast32_t offset,
2152            bool *okayp,
2153            bool do_norm_secs)
2154 {
2155           register int                            dir;
2156           register int                            i, j;
2157           register time_t                         lo;
2158           register time_t                         hi;
2159 #ifdef NO_ERROR_IN_DST_GAP
2160           time_t                                  ilo;
2161 #endif
2162           iinntt y, mday, hour, min, saved_seconds;
2163           time_t                                  newt;
2164           time_t                                  t;
2165           struct tm                     yourtm, mytm;
2166 
2167           *okayp = false;
2168           mktmcpy(&yourtm, tmp);
2169 
2170 #ifdef NO_ERROR_IN_DST_GAP
2171 again:
2172 #endif
2173           min = yourtm.tm_min;
2174           if (do_norm_secs) {
2175             min += yourtm.tm_sec / SECSPERMIN;
2176             yourtm.tm_sec %= SECSPERMIN;
2177             if (yourtm.tm_sec < 0) {
2178               yourtm.tm_sec += SECSPERMIN;
2179               min--;
2180             }
2181           }
2182 
2183           hour = yourtm.tm_hour;
2184           hour += min / MINSPERHOUR;
2185           yourtm.tm_min = min % MINSPERHOUR;
2186           if (yourtm.tm_min < 0) {
2187             yourtm.tm_min += MINSPERHOUR;
2188             hour--;
2189           }
2190 
2191           mday = yourtm.tm_mday;
2192           mday += hour / HOURSPERDAY;
2193           yourtm.tm_hour = hour % HOURSPERDAY;
2194           if (yourtm.tm_hour < 0) {
2195             yourtm.tm_hour += HOURSPERDAY;
2196             mday--;
2197           }
2198           y = yourtm.tm_year;
2199           y += yourtm.tm_mon / MONSPERYEAR;
2200           yourtm.tm_mon %= MONSPERYEAR;
2201           if (yourtm.tm_mon < 0) {
2202             yourtm.tm_mon += MONSPERYEAR;
2203             y--;
2204           }
2205 
2206           /*
2207           ** Turn y into an actual year number for now.
2208           ** It is converted back to an offset from TM_YEAR_BASE later.
2209           */
2210           y += TM_YEAR_BASE;
2211 
2212           while (mday <= 0) {
2213             iinntt li = y - (yourtm.tm_mon <= 1);
2214             mday += year_lengths[isleap(li)];
2215             y--;
2216           }
2217           while (DAYSPERLYEAR < mday) {
2218             iinntt li = y + (1 < yourtm.tm_mon);
2219             mday -= year_lengths[isleap(li)];
2220             y++;
2221           }
2222           yourtm.tm_mday = (int)mday;
2223           for ( ; ; ) {
2224                     i = mon_lengths[isleap(y)][yourtm.tm_mon];
2225                     if (yourtm.tm_mday <= i)
2226                               break;
2227                     yourtm.tm_mday -= i;
2228                     if (++yourtm.tm_mon >= MONSPERYEAR) {
2229                               yourtm.tm_mon = 0;
2230                               y++;
2231                     }
2232           }
2233 #ifdef ckd_add
2234           if (ckd_add(&yourtm.tm_year, y, -TM_YEAR_BASE))
2235                     goto out_of_range;
2236 #else
2237           y -= TM_YEAR_BASE;
2238           if (! (INT_MIN <= y && y <= INT_MAX))
2239                     goto out_of_range;
2240           yourtm.tm_year = (int)y;
2241 #endif
2242           if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
2243                     saved_seconds = 0;
2244           else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
2245                     /*
2246                     ** We can't set tm_sec to 0, because that might push the
2247                     ** time below the minimum representable time.
2248                     ** Set tm_sec to 59 instead.
2249                     ** This assumes that the minimum representable time is
2250                     ** not in the same minute that a leap second was deleted from,
2251                     ** which is a safer assumption than using 58 would be.
2252                     */
2253                     saved_seconds = yourtm.tm_sec;
2254                     saved_seconds -= SECSPERMIN - 1;
2255                     yourtm.tm_sec = SECSPERMIN - 1;
2256           } else {
2257                     saved_seconds = yourtm.tm_sec;
2258                     yourtm.tm_sec = 0;
2259           }
2260           /*
2261           ** Do a binary search (this works whatever time_t's type is).
2262           */
2263           lo = TIME_T_MIN;
2264           hi = TIME_T_MAX;
2265 #ifdef NO_ERROR_IN_DST_GAP
2266           ilo = lo;
2267 #endif
2268           for ( ; ; ) {
2269                     t = lo / 2 + hi / 2;
2270                     if (t < lo)
2271                               t = lo;
2272                     else if (t > hi)
2273                               t = hi;
2274                     if (! funcp(sp, &t, offset, &mytm)) {
2275                               /*
2276                               ** Assume that t is too extreme to be represented in
2277                               ** a struct tm; arrange things so that it is less
2278                               ** extreme on the next pass.
2279                               */
2280                               dir = (t > 0) ? 1 : -1;
2281                     } else    dir = tmcomp(&mytm, &yourtm);
2282                     if (dir != 0) {
2283                               if (t == lo) {
2284                                         if (t == TIME_T_MAX)
2285                                                   goto out_of_range;
2286                                         ++t;
2287                                         ++lo;
2288                               } else if (t == hi) {
2289                                         if (t == TIME_T_MIN)
2290                                                   goto out_of_range;
2291                                         --t;
2292                                         --hi;
2293                               }
2294 #ifdef NO_ERROR_IN_DST_GAP
2295                               if (ilo != lo && lo - 1 == hi && yourtm.tm_isdst < 0 &&
2296                                   do_norm_secs) {
2297                                         for (i = sp->typecnt - 1; i >= 0; --i) {
2298                                                   for (j = sp->typecnt - 1; j >= 0; --j) {
2299                                                             time_t off;
2300                                                             if (sp->ttis[j].tt_isdst ==
2301                                                                 sp->ttis[i].tt_isdst)
2302                                                                       continue;
2303                                                             if (ttunspecified(sp, j))
2304                                                                       continue;
2305                                                             off = sp->ttis[j].tt_utoff -
2306                                                                 sp->ttis[i].tt_utoff;
2307                                                             yourtm.tm_sec += off < 0 ?
2308                                                                 -off : off;
2309                                                             goto again;
2310                                                   }
2311                                         }
2312                               }
2313 #endif
2314                               if (lo > hi)
2315                                         goto invalid;
2316                               if (dir > 0)
2317                                         hi = t;
2318                               else      lo = t;
2319                               continue;
2320                     }
2321 #if defined TM_GMTOFF && ! UNINIT_TRAP
2322                     if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
2323                         && (yourtm.TM_GMTOFF < 0
2324                               ? (-SECSPERDAY <= yourtm.TM_GMTOFF
2325                                  && (mytm.TM_GMTOFF <=
2326                                      /*CONSTCOND*/
2327                                      (min(INT_FAST32_MAX, LONG_MAX)
2328                                         + yourtm.TM_GMTOFF)))
2329                               : (yourtm.TM_GMTOFF <= SECSPERDAY
2330                                      /*CONSTCOND*/
2331                                  && ((max(INT_FAST32_MIN, LONG_MIN)
2332                                         + yourtm.TM_GMTOFF)
2333                                      <= mytm.TM_GMTOFF)))) {
2334                       /* MYTM matches YOURTM except with the wrong UT offset.
2335                          YOURTM.TM_GMTOFF is plausible, so try it instead.
2336                          It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
2337                          since the guess gets checked.  */
2338                       __time_t altt = t;
2339                       int_fast32_t diff = (int_fast32_t)
2340                           (mytm.TM_GMTOFF - yourtm.TM_GMTOFF);
2341                       if (!increment_overflow_time(&altt, diff)) {
2342                         struct tm alttm;
2343                         time_t xaltt = (time_t)altt;
2344                         if (funcp(sp, &xaltt, offset, &alttm)
2345                               && alttm.tm_isdst == mytm.tm_isdst
2346                               && alttm.TM_GMTOFF == yourtm.TM_GMTOFF
2347                               && tmcomp(&alttm, &yourtm) == 0) {
2348                           t = xaltt;
2349                           mytm = alttm;
2350                         }
2351                       }
2352                     }
2353 #endif
2354                     if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2355                               break;
2356                     /*
2357                     ** Right time, wrong type.
2358                     ** Hunt for right time, right type.
2359                     ** It's okay to guess wrong since the guess
2360                     ** gets checked.
2361                     */
2362                     if (sp == NULL)
2363                               goto invalid;
2364                     for (i = sp->typecnt - 1; i >= 0; --i) {
2365                               if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2366                                         continue;
2367                               for (j = sp->typecnt - 1; j >= 0; --j) {
2368                                         if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2369                                                   continue;
2370                                         if (ttunspecified(sp, j))
2371                                           continue;
2372                                         newt = (time_t)(t + sp->ttis[j].tt_utoff -
2373                                             sp->ttis[i].tt_utoff);
2374                                         if (! funcp(sp, &newt, offset, &mytm))
2375                                                   continue;
2376                                         if (tmcomp(&mytm, &yourtm) != 0)
2377                                                   continue;
2378                                         if (mytm.tm_isdst != yourtm.tm_isdst)
2379                                                   continue;
2380                                         /*
2381                                         ** We have a match.
2382                                         */
2383                                         t = newt;
2384                                         goto label;
2385                               }
2386                     }
2387                     goto invalid;
2388           }
2389 label:
2390           if (increment_overflow_time_iinntt(&t, saved_seconds))
2391                     return WRONG;
2392           if (funcp(sp, &t, offset, tmp)) {
2393                     *okayp = true;
2394                     return t;
2395           }
2396 out_of_range:
2397           errno = EOVERFLOW;
2398           return WRONG;
2399 invalid:
2400           errno = EINVAL;
2401           return WRONG;
2402 }
2403 
2404 static time_t
time2(struct tm * const tmp,struct tm * (* funcp)(struct state const *,time_t const *,int_fast32_t,struct tm *),struct state const * sp,const int_fast32_t offset,bool * okayp)2405 time2(struct tm * const       tmp,
2406       struct tm *(*funcp)(struct state const *, time_t const *,
2407                                 int_fast32_t, struct tm *),
2408       struct state const *sp,
2409       const int_fast32_t offset,
2410       bool *okayp)
2411 {
2412           time_t    t;
2413 
2414           /*
2415           ** First try without normalization of seconds
2416           ** (in case tm_sec contains a value associated with a leap second).
2417           ** If that fails, try with normalization of seconds.
2418           */
2419           t = time2sub(tmp, funcp, sp, offset, okayp, false);
2420           return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
2421 }
2422 
2423 static time_t
time1(struct tm * const tmp,struct tm * (* funcp)(struct state const *,time_t const *,int_fast32_t,struct tm *),struct state const * sp,const int_fast32_t offset)2424 time1(struct tm *const tmp,
2425       struct tm *(*funcp)(struct state const *, time_t const *,
2426                                 int_fast32_t, struct tm *),
2427       struct state const *sp,
2428       const int_fast32_t offset)
2429 {
2430           register time_t                         t;
2431           register int                            samei, otheri;
2432           register int                            sameind, otherind;
2433           register int                            i;
2434           register int                            nseen;
2435           int                                     save_errno;
2436           char                                    seen[TZ_MAX_TYPES];
2437           unsigned char                           types[TZ_MAX_TYPES];
2438           bool                                    okay;
2439 
2440           if (tmp == NULL) {
2441                     errno = EINVAL;
2442                     return WRONG;
2443           }
2444           if (tmp->tm_isdst > 1)
2445                     tmp->tm_isdst = 1;
2446           save_errno = errno;
2447           t = time2(tmp, funcp, sp, offset, &okay);
2448           if (okay) {
2449                     errno = save_errno;
2450                     return t;
2451           }
2452           if (tmp->tm_isdst < 0)
2453 #ifdef PCTS
2454                     /*
2455                     ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
2456                     */
2457                     tmp->tm_isdst = 0;  /* reset to std and try again */
2458 #else
2459                     return t;
2460 #endif /* !defined PCTS */
2461           /*
2462           ** We're supposed to assume that somebody took a time of one type
2463           ** and did some math on it that yielded a "struct tm" that's bad.
2464           ** We try to divine the type they started from and adjust to the
2465           ** type they need.
2466           */
2467           if (sp == NULL) {
2468                     errno = EINVAL;
2469                     return WRONG;
2470           }
2471           for (i = 0; i < sp->typecnt; ++i)
2472                     seen[i] = false;
2473           nseen = 0;
2474           for (i = sp->timecnt - 1; i >= 0; --i)
2475                     if (!seen[sp->types[i]] && !ttunspecified(sp, sp->types[i])) {
2476                               seen[sp->types[i]] = true;
2477                               types[nseen++] = sp->types[i];
2478                     }
2479           for (sameind = 0; sameind < nseen; ++sameind) {
2480                     samei = types[sameind];
2481                     if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2482                               continue;
2483                     for (otherind = 0; otherind < nseen; ++otherind) {
2484                               otheri = types[otherind];
2485                               if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2486                                         continue;
2487                               tmp->tm_sec += (int)(sp->ttis[otheri].tt_utoff
2488                                                   - sp->ttis[samei].tt_utoff);
2489                               tmp->tm_isdst = !tmp->tm_isdst;
2490                               t = time2(tmp, funcp, sp, offset, &okay);
2491                               if (okay) {
2492                                         errno = save_errno;
2493                                         return t;
2494                               }
2495                               tmp->tm_sec -= (int)(sp->ttis[otheri].tt_utoff
2496                                                   - sp->ttis[samei].tt_utoff);
2497                               tmp->tm_isdst = !tmp->tm_isdst;
2498                     }
2499           }
2500           errno = EOVERFLOW;
2501           return WRONG;
2502 }
2503 
2504 #if !defined TM_GMTOFF || !USE_TIMEX_T
2505 
2506 static time_t
mktime_tzname(struct state * sp,struct tm * tmp,bool setname)2507 mktime_tzname(struct state *sp, struct tm *tmp, bool setname)
2508 {
2509   if (sp)
2510     return time1(tmp, localsub, sp, setname);
2511   else {
2512     gmtcheck();
2513     return time1(tmp, gmtsub, gmtptr, 0);
2514   }
2515 }
2516 
2517 # if USE_TIMEX_T
2518 static
2519 # endif
2520 time_t
mktime(struct tm * tmp)2521 mktime(struct tm *tmp)
2522 {
2523   time_t t;
2524   int err = lock();
2525   if (err) {
2526     errno = err;
2527     return -1;
2528   }
2529   tzset_unlocked();
2530   t = mktime_tzname(__lclptr, tmp, true);
2531   unlock();
2532   return t;
2533 }
2534 
2535 #endif
2536 
2537 #if NETBSD_INSPIRED && !USE_TIMEX_T
2538 time_t
mktime_z(struct state * restrict sp,struct tm * restrict tmp)2539 mktime_z(struct state *restrict sp, struct tm *restrict tmp)
2540 {
2541   return mktime_tzname(sp, tmp, false);
2542 }
2543 #endif
2544 
2545 #if STD_INSPIRED && !USE_TIMEX_T
2546 /* This function is obsolescent and may disappear in future releases.
2547    Callers can instead use mktime.  */
2548 time_t
timelocal_z(const timezone_t sp,struct tm * const tmp)2549 timelocal_z(const timezone_t sp, struct tm *const tmp)
2550 {
2551           if (tmp != NULL)
2552                     tmp->tm_isdst = -1; /* in case it wasn't initialized */
2553           return mktime_z(sp, tmp);
2554 }
2555 
2556 time_t
timelocal(struct tm * tmp)2557 timelocal(struct tm *tmp)
2558 {
2559           if (tmp != NULL)
2560                     tmp->tm_isdst = -1; /* in case it wasn't initialized */
2561           return mktime(tmp);
2562 }
2563 #endif
2564 
2565 #if defined TM_GMTOFF || !USE_TIMEX_T
2566 
2567 # ifndef EXTERN_TIMEOFF
2568 #  ifndef timeoff
2569 #   define timeoff my_timeoff /* Don't collide with OpenBSD 7.4 <time.h>.  */
2570 #  endif
2571 #  define EXTERN_TIMEOFF static
2572 # endif
2573 
2574 /* This function is obsolescent and may disappear in future releases.
2575    Callers can instead use mktime_z with a fixed-offset zone.  */
2576 EXTERN_TIMEOFF time_t
timeoff(struct tm * tmp,long offset)2577 timeoff(struct tm *tmp, long offset)
2578 {
2579   if (tmp)
2580     tmp->tm_isdst = 0;
2581   gmtcheck();
2582   return time1(tmp, gmtsub, gmtptr, (int_fast32_t)offset);
2583 }
2584 #endif
2585 
2586 #if !USE_TIMEX_T
2587 time_t
timegm(struct tm * tmp)2588 timegm(struct tm *tmp)
2589 {
2590   time_t t;
2591   struct tm tmcpy;
2592   mktmcpy(&tmcpy, tmp);
2593   tmcpy.tm_wday = -1;
2594   t = timeoff(&tmcpy, 0);
2595   if (0 <= tmcpy.tm_wday)
2596     *tmp = tmcpy;
2597   return t;
2598 }
2599 #endif
2600 
2601 static int_fast32_t
leapcorr(struct state const * sp,__time_t t)2602 leapcorr(struct state const *sp, __time_t t)
2603 {
2604           register struct lsinfo const *          lp;
2605           register int                            i;
2606 
2607           i = sp->leapcnt;
2608           while (--i >= 0) {
2609                     lp = &sp->lsis[i];
2610                     if (t >= lp->ls_trans)
2611                               return lp->ls_corr;
2612           }
2613           return 0;
2614 }
2615 
2616 /*
2617 ** XXX--is the below the right way to conditionalize??
2618 */
2619 
2620 #if !USE_TIMEX_T
2621 # if STD_INSPIRED
2622 
2623 /* NETBSD_INSPIRED_EXTERN functions are exported to callers if
2624    NETBSD_INSPIRED is defined, and are private otherwise.  */
2625 #  if NETBSD_INSPIRED
2626 #   define NETBSD_INSPIRED_EXTERN
2627 #  else
2628 #   define NETBSD_INSPIRED_EXTERN static
2629 #  endif
2630 
2631 /*
2632 ** IEEE Std 1003.1 (POSIX) says that 536457599
2633 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2634 ** is not the case if we are accounting for leap seconds.
2635 ** So, we provide the following conversion routines for use
2636 ** when exchanging timestamps with POSIX conforming systems.
2637 */
2638 
2639 NETBSD_INSPIRED_EXTERN time_t
time2posix_z(struct state * sp,time_t t)2640 time2posix_z(struct state *sp, time_t t)
2641 {
2642   return (time_t)(t - leapcorr(sp, t));
2643 }
2644 
2645 time_t
time2posix(time_t t)2646 time2posix(time_t t)
2647 {
2648   int err = lock();
2649   if (err) {
2650     errno = err;
2651     return -1;
2652   }
2653   if (!lcl_is_set)
2654     tzset_unlocked();
2655   if (__lclptr)
2656     t = (time_t)(t - leapcorr(__lclptr, t));
2657   unlock();
2658   return t;
2659 }
2660 
2661 NETBSD_INSPIRED_EXTERN time_t
posix2time_z(struct state * sp,time_t t)2662 posix2time_z(struct state *sp, time_t t)
2663 {
2664           time_t    x;
2665           time_t    y;
2666           /*
2667           ** For a positive leap second hit, the result
2668           ** is not unique. For a negative leap second
2669           ** hit, the corresponding time doesn't exist,
2670           ** so we return an adjacent second.
2671           */
2672           x = (time_t)(t + leapcorr(sp, t));
2673           y = (time_t)(x - leapcorr(sp, x));
2674           if (y < t) {
2675                     do {
2676                               x++;
2677                               y = (time_t)(x - leapcorr(sp, x));
2678                     } while (y < t);
2679                     x -= y != t;
2680           } else if (y > t) {
2681                     do {
2682                               --x;
2683                               y = (time_t)(x - leapcorr(sp, x));
2684                     } while (y > t);
2685                     x += y != t;
2686           }
2687           return x;
2688 }
2689 
2690 time_t
posix2time(time_t t)2691 posix2time(time_t t)
2692 {
2693   int err = lock();
2694   if (err) {
2695     errno = err;
2696     return -1;
2697   }
2698   if (!lcl_is_set)
2699     tzset_unlocked();
2700   if (__lclptr)
2701     t = posix2time_z(__lclptr, t);
2702   unlock();
2703   return t;
2704 }
2705 
2706 # endif /* STD_INSPIRED */
2707 
2708 # if TZ_TIME_T
2709 
2710 #  if !USG_COMPAT
2711 #   define timezone 0
2712 #  endif
2713 
2714 /* Convert from the underlying system's time_t to the ersatz time_tz,
2715    which is called 'time_t' in this file.  Typically, this merely
2716    converts the time's integer width.  On some platforms, the system
2717    time is local time not UT, or uses some epoch other than the POSIX
2718    epoch.
2719 
2720    Although this code appears to define a function named 'time' that
2721    returns time_t, the macros in private.h cause this code to actually
2722    define a function named 'tz_time' that returns tz_time_t.  The call
2723    to sys_time invokes the underlying system's 'time' function.  */
2724 
2725 time_t
time(time_t * p)2726 time(time_t *p)
2727 {
2728   __time_t r = sys_time(0);
2729   if (r != (time_t) -1) {
2730     iinntt offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
2731     if (offset < IINNTT_MIN + EPOCH_OFFSET
2732           || increment_overflow_time_iinntt(&r, offset - EPOCH_OFFSET)) {
2733       errno = EOVERFLOW;
2734       r = -1;
2735     }
2736   }
2737   if (p)
2738     *p = (time_t)r;
2739   return (time_t)r;
2740 }
2741 
2742 # endif
2743 #endif
2744 
2745