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