1+ /* Convert timestamp from pg_time_t to struct pg_tm. */
2+
13/*
24 * This file is in the public domain, so clarified as of
35 * 1996-06-05 by Arthur David Olson.
@@ -117,7 +119,7 @@ init_ttinfo(struct ttinfo *s, int32 gmtoff, bool isdst, int abbrind)
117119}
118120
119121static int32
120- detzcode (const char * codep )
122+ detzcode (const char * const codep )
121123{
122124int32 result ;
123125int i ;
@@ -143,7 +145,7 @@ detzcode(const char *codep)
143145}
144146
145147static int64
146- detzcode64 (const char * codep )
148+ detzcode64 (const char * const codep )
147149{
148150uint64 result ;
149151int i ;
@@ -258,8 +260,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
258260int32 charcnt = detzcode (up -> tzhead .tzh_charcnt );
259261char const * p = up -> buf + tzheadsize ;
260262
263+ /*
264+ * Although tzfile(5) currently requires typecnt to be nonzero,
265+ * support future formats that may allow zero typecnt in files that
266+ * have a TZ string and no transitions.
267+ */
261268if (!(0 <=leapcnt && leapcnt < TZ_MAX_LEAPS
262- && 0 < typecnt && typecnt < TZ_MAX_TYPES
269+ && 0 <= typecnt && typecnt < TZ_MAX_TYPES
263270&& 0 <=timecnt && timecnt < TZ_MAX_TIMES
264271&& 0 <=charcnt && charcnt < TZ_MAX_CHARS
265272&& (ttisstdcnt == typecnt || ttisstdcnt == 0 )
@@ -416,8 +423,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
416423struct state * ts = & lsp -> u .st ;
417424
418425up -> buf [nread - 1 ]= '\0' ;
419- if (tzparse (& up -> buf [1 ],ts , false)
420- && ts -> typecnt == 2 )
426+ if (tzparse (& up -> buf [1 ],ts , false))
421427{
422428/*
423429 * Attempt to reuse existing abbreviations. Without this,
@@ -430,7 +436,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
430436int gotabbr = 0 ;
431437int charcnt = sp -> charcnt ;
432438
433- for (i = 0 ;i < 2 ;i ++ )
439+ for (i = 0 ;i < ts -> typecnt ;i ++ )
434440{
435441char * tsabbr = ts -> chars + ts -> ttis [i ].tt_abbrind ;
436442int j ;
@@ -455,7 +461,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
455461}
456462}
457463}
458- if (gotabbr == 2 )
464+ if (gotabbr == ts -> typecnt )
459465{
460466sp -> charcnt = charcnt ;
461467
@@ -470,7 +476,8 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
470476sp -> timecnt -- ;
471477
472478for (i = 0 ;i < ts -> timecnt ;i ++ )
473- if (sp -> ats [sp -> timecnt - 1 ]< ts -> ats [i ])
479+ if (sp -> timecnt == 0
480+ || sp -> ats [sp -> timecnt - 1 ]< ts -> ats [i ])
474481break ;
475482while (i < ts -> timecnt
476483&& sp -> timecnt < TZ_MAX_TIMES )
@@ -481,11 +488,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
481488sp -> timecnt ++ ;
482489i ++ ;
483490}
484- sp -> ttis [ sp -> typecnt ++ ] = ts -> ttis [ 0 ];
485- sp -> ttis [sp -> typecnt ++ ]= ts -> ttis [1 ];
491+ for ( i = 0 ; i < ts -> typecnt ; i ++ )
492+ sp -> ttis [sp -> typecnt ++ ]= ts -> ttis [i ];
486493}
487494}
488495}
496+ if (sp -> typecnt == 0 )
497+ return EINVAL ;
489498if (sp -> timecnt > 1 )
490499{
491500for (i = 1 ;i < sp -> timecnt ;++ i )
@@ -506,6 +515,18 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
506515}
507516}
508517
518+ /*
519+ * Infer sp->defaulttype from the data. Although this default type is
520+ * always zero for data from recent tzdb releases, things are trickier for
521+ * data from tzdb 2018e or earlier.
522+ *
523+ * The first set of heuristics work around bugs in 32-bit data generated
524+ * by tzdb 2013c or earlier. The workaround is for zones like
525+ * Australia/Macquarie where timestamps before the first transition have a
526+ * time type that is not the earliest standard-time type. See:
527+ * https://mm.icann.org/pipermail/tz/2013-May/019368.html
528+ */
529+
509530/*
510531 * If type 0 is unused in transitions, it's the type to use for early
511532 * times.
@@ -528,6 +549,11 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
528549break ;
529550}
530551
552+ /*
553+ * The next heuristics are for data generated by tzdb 2018e or earlier,
554+ * for zones like EST5EDT where the first transition is to DST.
555+ */
556+
531557/*
532558 * If no result yet, find the first standard type. If there is none, punt
533559 * to type zero.
@@ -542,7 +568,14 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
542568break ;
543569}
544570}
571+
572+ /*
573+ * A simple 'sp->defaulttype = 0;' would suffice here if we didn't have to
574+ * worry about 2018e-or-earlier data. Even simpler would be to remove the
575+ * defaulttype member and just use 0 in its place.
576+ */
545577sp -> defaulttype = i ;
578+
546579return 0 ;
547580}
548581
@@ -601,10 +634,11 @@ static const int year_lengths[2] = {
601634};
602635
603636/*
604- * Given a pointer into atime zone string, scan until a character that is not
605- * a valid character in a zonename is found. Return a pointer to that
606- * character.
637+ * Given a pointer into atimezone string, scan until a character that is not
638+ * a valid character in atime zoneabbreviation is found.
639+ *Return a pointer to that character.
607640 */
641+
608642static const char *
609643getzname (const char * strp )
610644{
@@ -617,15 +651,17 @@ getzname(const char *strp)
617651}
618652
619653/*
620- * Given a pointer into an extended time zone string, scan until the ending
621- * delimiter of the zone name is located. Return a pointer to the delimiter.
654+ * Given a pointer into an extended timezone string, scan until the ending
655+ * delimiter of the time zone abbreviation is located.
656+ * Return a pointer to the delimiter.
622657 *
623658 * As with getzname above, the legal character set is actually quite
624659 * restricted, with other characters producing undefined results.
625660 * We don't do any checking here; checking is done later in common-case code.
626661 */
662+
627663static const char *
628- getqzname (const char * strp ,int delim )
664+ getqzname (const char * strp ,const int delim )
629665{
630666int c ;
631667
@@ -635,13 +671,14 @@ getqzname(const char *strp, int delim)
635671}
636672
637673/*
638- * Given a pointer into atime zone string, extract a number from that string.
674+ * Given a pointer into atimezone string, extract a number from that string.
639675 * Check that the number is within a specified range; if it is not, return
640676 * NULL.
641677 * Otherwise, return a pointer to the first character not part of the number.
642678 */
679+
643680static const char *
644- getnum (const char * strp ,int * nump ,int min ,int max )
681+ getnum (const char * strp ,int * const nump ,const int min ,const int max )
645682{
646683char c ;
647684int num ;
@@ -663,14 +700,15 @@ getnum(const char *strp, int *nump, int min, int max)
663700}
664701
665702/*
666- * Given a pointer into atime zone string, extract a number of seconds,
703+ * Given a pointer into atimezone string, extract a number of seconds,
667704 * in hh[:mm[:ss]] form, from the string.
668705 * If any error occurs, return NULL.
669706 * Otherwise, return a pointer to the first character not part of the number
670707 * of seconds.
671708 */
709+
672710static const char *
673- getsecs (const char * strp ,int32 * secsp )
711+ getsecs (const char * strp ,int32 * const secsp )
674712{
675713int num ;
676714
@@ -704,13 +742,14 @@ getsecs(const char *strp, int32 *secsp)
704742}
705743
706744/*
707- * Given a pointer into atime zone string, extract an offset, in
745+ * Given a pointer into atimezone string, extract an offset, in
708746 * [+-]hh[:mm[:ss]] form, from the string.
709747 * If any error occurs, return NULL.
710748 * Otherwise, return a pointer to the first character not part of the time.
711749 */
750+
712751static const char *
713- getoffset (const char * strp ,int32 * offsetp )
752+ getoffset (const char * strp ,int32 * const offsetp )
714753{
715754bool neg = false;
716755
@@ -730,13 +769,14 @@ getoffset(const char *strp, int32 *offsetp)
730769}
731770
732771/*
733- * Given a pointer into atime zone string, extract a rule in the form
772+ * Given a pointer into atimezone string, extract a rule in the form
734773 * date[/time]. See POSIX section 8 for the format of "date" and "time".
735774 * If a valid rule is not found, return NULL.
736775 * Otherwise, return a pointer to the first character not part of the rule.
737776 */
777+
738778static const char *
739- getrule (const char * strp ,struct rule * rulep )
779+ getrule (const char * strp ,struct rule * const rulep )
740780{
741781if (* strp == 'J' )
742782{
@@ -795,9 +835,10 @@ getrule(const char *strp, struct rule *rulep)
795835 * Given a year, a rule, and the offset from UT at the time that rule takes
796836 * effect, calculate the year-relative time that rule takes effect.
797837 */
838+
798839static int32
799- transtime (int year ,const struct rule * rulep ,
800- int32 offset )
840+ transtime (const int year ,const struct rule * const rulep ,
841+ const int32 offset )
801842{
802843bool leapyear ;
803844int32 value ;
@@ -967,7 +1008,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
9671008{
9681009dstname = name ;
9691010name = getzname (name );
970- dstlen = name - dstname ;/* length of DSTzone name */
1011+ dstlen = name - dstname ;/* length of DSTabbr. */
9711012}
9721013if (!dstlen )
9731014return false;
@@ -1039,8 +1080,8 @@ tzparse(const char *name, struct state *sp, bool lastditch)
10391080/*
10401081 * Two transitions per year, from EPOCH_YEAR forward.
10411082 */
1042- init_ttinfo (& sp -> ttis [0 ],- dstoffset , true, stdlen + 1 );
1043- init_ttinfo (& sp -> ttis [1 ],- stdoffset , false, 0 );
1083+ init_ttinfo (& sp -> ttis [0 ],- stdoffset , false, 0 );
1084+ init_ttinfo (& sp -> ttis [1 ],- dstoffset , true, stdlen + 1 );
10441085sp -> defaulttype = 0 ;
10451086timecnt = 0 ;
10461087janfirst = 0 ;
@@ -1089,19 +1130,15 @@ tzparse(const char *name, struct state *sp, bool lastditch)
10891130if (!increment_overflow_time
10901131(& sp -> ats [timecnt ],
10911132janoffset + starttime ))
1092- sp -> types [timecnt ++ ]= reversed ;
1093- else if (janoffset )
1094- sp -> defaulttype = reversed ;
1133+ sp -> types [timecnt ++ ]= !reversed ;
10951134sp -> ats [timecnt ]= janfirst ;
10961135if (!increment_overflow_time
10971136(& sp -> ats [timecnt ],
10981137janoffset + endtime ))
10991138{
1100- sp -> types [timecnt ++ ]= ! reversed ;
1139+ sp -> types [timecnt ++ ]= reversed ;
11011140yearlim = year + YEARSPERREPEAT + 1 ;
11021141}
1103- else if (janoffset )
1104- sp -> defaulttype = !reversed ;
11051142}
11061143if (increment_overflow_time
11071144(& janfirst ,janoffset + yearsecs ))
@@ -1110,7 +1147,10 @@ tzparse(const char *name, struct state *sp, bool lastditch)
11101147}
11111148sp -> timecnt = timecnt ;
11121149if (!timecnt )
1150+ {
1151+ sp -> ttis [0 ]= sp -> ttis [1 ];
11131152sp -> typecnt = 1 ;/* Perpetual DST. */
1153+ }
11141154else if (YEARSPERREPEAT < year - yearbeg )
11151155sp -> goback = sp -> goahead = true;
11161156}
@@ -1179,7 +1219,6 @@ tzparse(const char *name, struct state *sp, bool lastditch)
11791219 * otherwise, add the standard time offset to the
11801220 * transition time.
11811221 */
1182-
11831222/*
11841223 * Transitions from DST to DDST will effectively disappear
11851224 * since POSIX provides for only one DST offset.
@@ -1233,7 +1272,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
12331272}
12341273
12351274static void
1236- gmtload (struct state * sp )
1275+ gmtload (struct state * const sp )
12371276{
12381277if (tzload (gmt ,NULL ,sp , true)!= 0 )
12391278tzparse (gmt ,sp , true);
@@ -1248,7 +1287,7 @@ gmtload(struct state *sp)
12481287 */
12491288static struct pg_tm *
12501289localsub (struct state const * sp ,pg_time_t const * timep ,
1251- struct pg_tm * tmp )
1290+ struct pg_tm * const tmp )
12521291{
12531292const struct ttinfo * ttisp ;
12541293int i ;
@@ -1316,6 +1355,11 @@ localsub(struct state const *sp, pg_time_t const *timep,
13161355}
13171356ttisp = & sp -> ttis [i ];
13181357
1358+ /*
1359+ * To get (wrong) behavior that's compatible with System V Release 2.0
1360+ * you'd replace the statement below with t += ttisp->tt_gmtoff;
1361+ * timesub(&t, 0L, sp, tmp);
1362+ */
13191363result = timesub (& t ,ttisp -> tt_gmtoff ,sp ,tmp );
13201364if (result )
13211365{
@@ -1338,8 +1382,10 @@ pg_localtime(const pg_time_t *timep, const pg_tz *tz)
13381382 *
13391383 * Except we have a private "struct state" for GMT, so no sp is passed in.
13401384 */
1385+
13411386static struct pg_tm *
1342- gmtsub (pg_time_t const * timep ,int32 offset ,struct pg_tm * tmp )
1387+ gmtsub (pg_time_t const * timep ,int32 offset ,
1388+ struct pg_tm * tmp )
13431389{
13441390struct pg_tm * result ;
13451391
@@ -1354,6 +1400,7 @@ gmtsub(pg_time_t const *timep, int32 offset, struct pg_tm *tmp)
13541400return NULL ;/* errno should be set by malloc */
13551401gmtload (gmtptr );
13561402}
1403+
13571404result = timesub (timep ,offset ,gmtptr ,tmp );
13581405
13591406/*
@@ -1378,6 +1425,7 @@ pg_gmtime(const pg_time_t *timep)
13781425 * Return the number of leap years through the end of the given year
13791426 * where, to make the math easy, the answer for year zero is defined as zero.
13801427 */
1428+
13811429static int
13821430leaps_thru_end_of_nonneg (int y )
13831431{