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