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{
122124 int32 result ;
123125 int 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{
148150 uint64 result ;
149151 int i ;
@@ -258,8 +260,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
258260 int32 charcnt = detzcode (up -> tzhead .tzh_charcnt );
259261 char 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+ */
261268 if (!(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,
416423 struct state * ts = & lsp -> u .st ;
417424
418425 up -> 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,
430436 int gotabbr = 0 ;
431437 int charcnt = sp -> charcnt ;
432438
433- for (i = 0 ; i < 2 ; i ++ )
439+ for (i = 0 ; i < ts -> typecnt ; i ++ )
434440 {
435441 char * tsabbr = ts -> chars + ts -> ttis [i ].tt_abbrind ;
436442 int 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 {
460466 sp -> charcnt = charcnt ;
461467
@@ -470,7 +476,8 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
470476 sp -> timecnt -- ;
471477
472478 for (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 ])
474481 break ;
475482 while (i < ts -> timecnt
476483 && sp -> timecnt < TZ_MAX_TIMES )
@@ -481,11 +488,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
481488 sp -> timecnt ++ ;
482489 i ++ ;
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 ;
489498 if (sp -> timecnt > 1 )
490499 {
491500 for (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,
528549 break ;
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,
542568 break ;
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+ */
545577 sp -> defaulttype = i ;
578+
546579 return 0 ;
547580}
548581
@@ -601,10 +634,11 @@ static const int year_lengths[2] = {
601634};
602635
603636/*
604- * Given a pointer into a time zone string, scan until a character that is not
605- * a valid character in a zone name is found. Return a pointer to that
606- * character.
637+ * Given a pointer into a timezone string, scan until a character that is not
638+ * a valid character in a time zone abbreviation 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{
630666 int c ;
631667
@@ -635,13 +671,14 @@ getqzname(const char *strp, int delim)
635671}
636672
637673/*
638- * Given a pointer into a time zone string, extract a number from that string.
674+ * Given a pointer into a timezone 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{
646683 char c ;
647684 int num ;
@@ -663,14 +700,15 @@ getnum(const char *strp, int *nump, int min, int max)
663700}
664701
665702/*
666- * Given a pointer into a time zone string, extract a number of seconds,
703+ * Given a pointer into a timezone 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{
675713 int num ;
676714
@@ -704,13 +742,14 @@ getsecs(const char *strp, int32 *secsp)
704742}
705743
706744/*
707- * Given a pointer into a time zone string, extract an offset, in
745+ * Given a pointer into a timezone 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{
715754 bool neg = false;
716755
@@ -730,13 +769,14 @@ getoffset(const char *strp, int32 *offsetp)
730769}
731770
732771/*
733- * Given a pointer into a time zone string, extract a rule in the form
772+ * Given a pointer into a timezone 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{
741781 if (* 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{
802843 bool leapyear ;
803844 int32 value ;
@@ -967,7 +1008,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
9671008 {
9681009 dstname = name ;
9691010 name = getzname (name );
970- dstlen = name - dstname ; /* length of DST zone name */
1011+ dstlen = name - dstname ; /* length of DST abbr. */
9711012 }
9721013 if (!dstlen )
9731014 return 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 );
10441085 sp -> defaulttype = 0 ;
10451086 timecnt = 0 ;
10461087 janfirst = 0 ;
@@ -1089,19 +1130,15 @@ tzparse(const char *name, struct state *sp, bool lastditch)
10891130 if (!increment_overflow_time
10901131 (& sp -> ats [timecnt ],
10911132 janoffset + starttime ))
1092- sp -> types [timecnt ++ ] = reversed ;
1093- else if (janoffset )
1094- sp -> defaulttype = reversed ;
1133+ sp -> types [timecnt ++ ] = !reversed ;
10951134 sp -> ats [timecnt ] = janfirst ;
10961135 if (!increment_overflow_time
10971136 (& sp -> ats [timecnt ],
10981137 janoffset + endtime ))
10991138 {
1100- sp -> types [timecnt ++ ] = ! reversed ;
1139+ sp -> types [timecnt ++ ] = reversed ;
11011140 yearlim = year + YEARSPERREPEAT + 1 ;
11021141 }
1103- else if (janoffset )
1104- sp -> defaulttype = !reversed ;
11051142 }
11061143 if (increment_overflow_time
11071144 (& janfirst , janoffset + yearsecs ))
@@ -1110,7 +1147,10 @@ tzparse(const char *name, struct state *sp, bool lastditch)
11101147 }
11111148 sp -> timecnt = timecnt ;
11121149 if (!timecnt )
1150+ {
1151+ sp -> ttis [0 ] = sp -> ttis [1 ];
11131152 sp -> typecnt = 1 ; /* Perpetual DST. */
1153+ }
11141154 else if (YEARSPERREPEAT < year - yearbeg )
11151155 sp -> 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{
12381277 if (tzload (gmt , NULL , sp , true) != 0 )
12391278 tzparse (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{
12531292 const struct ttinfo * ttisp ;
12541293 int i ;
@@ -1316,6 +1355,11 @@ localsub(struct state const *sp, pg_time_t const *timep,
13161355 }
13171356 ttisp = & 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+ */
13191363 result = timesub (& t , ttisp -> tt_gmtoff , sp , tmp );
13201364 if (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{
13441390 struct pg_tm * result ;
13451391
@@ -1354,6 +1400,7 @@ gmtsub(pg_time_t const *timep, int32 offset, struct pg_tm *tmp)
13541400 return NULL ; /* errno should be set by malloc */
13551401 gmtload (gmtptr );
13561402 }
1403+
13571404 result = 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{
0 commit comments