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