LCOV - code coverage report
Current view: top level - src/timezone - localtime.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 82.8 % 793 657
Test Date: 2026-07-02 08:16:32 Functions: 94.6 % 37 35
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Convert timestamp from pg_time_t to struct pg_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              :  * IDENTIFICATION
       8              :  *    src/timezone/localtime.c
       9              :  */
      10              : 
      11              : /*
      12              :  * Leap second handling from Bradley White.
      13              :  * POSIX.1-1988 style TZ environment variable handling from Guy Harris.
      14              :  */
      15              : 
      16              : /* this file needs to build in both frontend and backend contexts */
      17              : #include "c.h"
      18              : 
      19              : #include <fcntl.h>
      20              : 
      21              : #include "datatype/timestamp.h"
      22              : #include "pgtz.h"
      23              : 
      24              : #include "private.h"
      25              : #include "tzfile.h"
      26              : 
      27              : 
      28              : /*
      29              :  * Pacify gcc -Wcast-qual on char const * exprs.
      30              :  * Use this carefully, as the casts disable type checking.
      31              :  * This is a macro so that it can be used in static initializers.
      32              :  */
      33              : #define UNCONST(a) unconstify(char *, a)
      34              : 
      35              : #ifndef WILDABBR
      36              : /*
      37              :  * Someone might make incorrect use of a time zone abbreviation:
      38              :  *  1.  They might reference tzname[0] before calling tzset (explicitly
      39              :  *      or implicitly).
      40              :  *  2.  They might reference tzname[1] before calling tzset (explicitly
      41              :  *      or implicitly).
      42              :  *  3.  They might reference tzname[1] after setting to a time zone
      43              :  *      in which Daylight Saving Time is never observed.
      44              :  *  4.  They might reference tzname[0] after setting to a time zone
      45              :  *      in which Standard Time is never observed.
      46              :  *  5.  They might reference tm.TM_ZONE after calling offtime.
      47              :  * What's best to do in the above cases is open to debate;
      48              :  * for now, we just set things up so that in any of the five cases
      49              :  * WILDABBR is used. Another possibility: initialize tzname[0] to the
      50              :  * string "tzname[0] used before set", and similarly for the other cases.
      51              :  * And another: initialize tzname[0] to "ERA", with an explanation in the
      52              :  * manual page of what this "time zone abbreviation" means (doing this so
      53              :  * that tzname[0] has the "normal" length of three characters).
      54              :  */
      55              : #define WILDABBR "   "
      56              : #endif                          /* !defined WILDABBR */
      57              : 
      58              : static const char wildabbr[] = WILDABBR;
      59              : 
      60              : /*
      61              :  * The DST rules to use if TZ has no rules.
      62              :  * Default to US rules as of 2017-05-07.
      63              :  * POSIX does not specify the default DST rules;
      64              :  * for historical reasons, US rules are a common default.
      65              :  */
      66              : #ifndef TZDEFRULESTRING
      67              : #define TZDEFRULESTRING ",M3.2.0,M11.1.0"
      68              : #endif
      69              : 
      70              : /* TZNAME_MAXIMUM and types ttinfo, lsinfo, state have been moved to pgtz.h */
      71              : 
      72              : static int
      73      7007040 : leapcount(ATTRIBUTE_MAYBE_UNUSED struct state const *sp)
      74              : {
      75              : #if TZ_RUNTIME_LEAPS
      76      7007040 :     return sp->leapcnt;
      77              : #else
      78              :     return 0;
      79              : #endif
      80              : }
      81              : static void
      82        37780 : set_leapcount(ATTRIBUTE_MAYBE_UNUSED struct state *sp,
      83              :               ATTRIBUTE_MAYBE_UNUSED int leapcnt)
      84              : {
      85              : #if TZ_RUNTIME_LEAPS
      86        37780 :     sp->leapcnt = leapcnt;
      87              : #endif
      88        37780 : }
      89              : static struct lsinfo
      90            0 : lsinfo(ATTRIBUTE_MAYBE_UNUSED struct state const *sp,
      91              :        ATTRIBUTE_MAYBE_UNUSED int i)
      92              : {
      93              : #if TZ_RUNTIME_LEAPS
      94            0 :     return sp->lsis[i];
      95              : #else
      96              :     unreachable();
      97              : #endif
      98              : }
      99              : static void
     100            0 : set_lsinfo(ATTRIBUTE_MAYBE_UNUSED struct state *sp,
     101              :            ATTRIBUTE_MAYBE_UNUSED int i,
     102              :            ATTRIBUTE_MAYBE_UNUSED struct lsinfo lsinfo)
     103              : {
     104              : #if TZ_RUNTIME_LEAPS
     105            0 :     sp->lsis[i] = lsinfo;
     106              : #endif
     107            0 : }
     108              : 
     109              : enum r_type
     110              : {
     111              :     JULIAN_DAY,                 /* Jn = Julian day */
     112              :     DAY_OF_YEAR,                /* n = day of year */
     113              :     MONTH_NTH_DAY_OF_WEEK       /* Mm.n.d = month, week, day of week */
     114              : };
     115              : 
     116              : struct rule
     117              : {
     118              :     enum r_type r_type;         /* type of rule */
     119              :     int         r_day;          /* day number of rule */
     120              :     int         r_week;         /* week number of rule */
     121              :     int         r_mon;          /* month number of rule */
     122              :     int_fast32_t r_time;        /* transition time of rule */
     123              : };
     124              : 
     125              : /*
     126              :  * Prototypes for static functions.
     127              :  */
     128              : 
     129              : static struct pg_tm *gmtsub(pg_time_t const *timep, int_fast32_t offset,
     130              :                             struct pg_tm *tmp);
     131              : static bool increment_overflow(int *ip, int j);
     132              : static bool increment_overflow_time(pg_time_t *tp, int_fast32_2s j);
     133              : static int_fast32_2s leapcorr(struct state const *sp, pg_time_t t);
     134              : static struct pg_tm *timesub(pg_time_t const *timep,
     135              :                              int_fast32_t offset, struct state const *sp,
     136              :                              struct pg_tm *tmp);
     137              : static bool tzparse(const char *name, struct state *sp, struct state const *basep);
     138              : 
     139              : 
     140              : /*
     141              :  * Section 4.12.3 of X3.159-1989 requires that
     142              :  *  Except for the strftime function, these functions [asctime,
     143              :  *  ctime, gmtime, localtime] return values in one of two static
     144              :  *  objects: a broken-down time structure and an array of char.
     145              :  * Thanks to Paul Eggert for noting this.
     146              :  */
     147              : 
     148              : static struct pg_tm tm;
     149              : 
     150              : /* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX.  */
     151              : static void
     152        20447 : init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst,
     153              :             desigidx_type desigidx)
     154              : {
     155        20447 :     s->tt_utoff = utoff;
     156        20447 :     s->tt_isdst = isdst;
     157        20447 :     s->tt_desigidx = desigidx;
     158        20447 :     s->tt_ttisstd = false;
     159        20447 :     s->tt_ttisut = false;
     160        20447 : }
     161              : 
     162              : static int_fast32_2s
     163       196529 : detzcode(const char *const codep)
     164              : {
     165              :     int         i;
     166              :     int_fast32_2s
     167       196529 :                 maxval = TWO_31_MINUS_1,
     168       196529 :                 minval = -1 - maxval,
     169              :                 result;
     170              : 
     171       196529 :     result = codep[0] & 0x7f;
     172       786116 :     for (i = 1; i < 4; ++i)
     173       589587 :         result = (result << 8) | (codep[i] & 0xff);
     174              : 
     175       196529 :     if (codep[0] & 0x80)
     176              :     {
     177              :         /*
     178              :          * Do two's-complement negation even on non-two's-complement machines.
     179              :          * This cannot overflow, as int_fast32_2s is wide enough.
     180              :          */
     181        35929 :         result += minval;
     182              :     }
     183       196529 :     return result;
     184              : }
     185              : 
     186              : static int_fast64_t
     187       881871 : detzcode64(const char *const codep)
     188              : {
     189              :     int_fast64_t result;
     190              :     int         i;
     191       881871 :     int_fast64_t one = 1;
     192       881871 :     int_fast64_t halfmaxval = one << (64 - 2);
     193       881871 :     int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
     194       881871 :     int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
     195              : 
     196       881871 :     result = codep[0] & 0x7f;
     197      7054968 :     for (i = 1; i < 8; ++i)
     198      6173097 :         result = (result << 8) | (codep[i] & 0xff);
     199              : 
     200       881871 :     if (codep[0] & 0x80)
     201              :     {
     202              :         /*
     203              :          * Do two's-complement negation even on non-two's-complement machines.
     204              :          * If the result would be minval - 1, return minval.
     205              :          */
     206       338489 :         result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
     207       338489 :         result += minval;
     208              :     }
     209       881871 :     return result;
     210              : }
     211              : 
     212              : /* Input buffer for data read from a compiled tz file.  */
     213              : union input_buffer
     214              : {
     215              :     /* The first part of the buffer, interpreted as a header.  */
     216              :     struct tzhead tzhead;
     217              : 
     218              :     /*
     219              :      * The entire buffer.  Ideally this would have no size limits; the
     220              :      * following should suffice for practical use.
     221              :      */
     222              :     char        buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
     223              :                     + 4 * TZ_MAX_TIMES];
     224              : };
     225              : 
     226              : /* Local storage needed for 'tzloadbody'.  */
     227              : union local_storage
     228              : {
     229              :     /* The results of analyzing the file's contents after it is opened.  */
     230              :     struct file_analysis
     231              :     {
     232              :         /* The input buffer.  */
     233              :         union input_buffer u;
     234              : 
     235              :         /* A temporary state used for parsing a TZ string in the file.  */
     236              :         struct state st;
     237              :     }           u;
     238              : 
     239              :     /* PG: we don't need the "fullname" member */
     240              : };
     241              : 
     242              : /* These tzload flags can be ORed together, and fit into 'char'.  */
     243              : enum
     244              : {
     245              : TZLOAD_FROMENV = 1};            /* The TZ string came from the environment.  */
     246              : enum
     247              : {
     248              : TZLOAD_TZSTRING = 2};           /* Read any newline-surrounded TZ string.  */
     249              : enum
     250              : {
     251              : TZLOAD_TZDIR_SUB = 4};          /* TZ should be a file under TZDIR.  */
     252              : 
     253              : /*
     254              :  * Load tz data from the file named NAME into *SP.  Respect TZLOADFLAGS.
     255              :  * Use **LSPP for temporary storage.  Return 0 on
     256              :  * success, an errno value on failure.
     257              :  * PG: If "canonname" is not NULL, then on success the canonical spelling of
     258              :  * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
     259              :  */
     260              : static int
     261        12307 : tzloadbody(char const *name, char *canonname,
     262              :            struct state *sp, char tzloadflags,
     263              :            union local_storage **lspp)
     264              : {
     265              :     int         i;
     266              :     int         fid;
     267              :     int         stored;
     268              :     ssize_t     nread;
     269        12307 :     union local_storage *lsp = *lspp;
     270              :     union input_buffer *up;
     271        12307 :     int         tzheadsize = sizeof(struct tzhead);
     272              : 
     273        12307 :     sp->goback = sp->goahead = false;
     274              : 
     275        12307 :     if (!name)
     276              :     {
     277            0 :         name = TZDEFAULT;
     278            0 :         if (!name)
     279            0 :             return EINVAL;
     280              :     }
     281              : 
     282        12307 :     if (name[0] == ':')
     283            0 :         ++name;
     284              : 
     285              :     /*
     286              :      * The IANA code goes to a great deal of trouble here to try to prevent
     287              :      * inappropriate file accesses.  That seems unnecessary for PG since we
     288              :      * won't run as root.  pg_open_tzfile() does go to some effort to prevent
     289              :      * accesses outside the designated zoneinfo tree, though.
     290              :      */
     291        12307 :     fid = pg_open_tzfile(name, canonname);
     292        12307 :     if (fid < 0)
     293          289 :         return ENOENT;          /* pg_open_tzfile may not set errno */
     294              : 
     295        12018 :     up = &lsp->u.u;
     296        12018 :     nread = read(fid, up->buf, sizeof up->buf);
     297        12018 :     if (nread < tzheadsize)
     298              :     {
     299            0 :         int         err = nread < 0 ? errno : EINVAL;
     300              : 
     301            0 :         close(fid);
     302            0 :         return err;
     303              :     }
     304        12018 :     if (close(fid) < 0)
     305            0 :         return errno;
     306              : 
     307        36054 :     for (stored = 4; stored <= 8; stored *= 2)
     308              :     {
     309        24036 :         char        version = up->tzhead.tzh_version[0];
     310        24036 :         bool        skip_datablock = stored == 4 && version;
     311              :         int_fast32_t datablock_size;
     312              :         int_fast32_2s
     313        24036 :                     ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt),
     314        24036 :                     ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt),
     315        24036 :                     leapcnt = detzcode(up->tzhead.tzh_leapcnt),
     316        24036 :                     timecnt = detzcode(up->tzhead.tzh_timecnt),
     317        24036 :                     typecnt = detzcode(up->tzhead.tzh_typecnt),
     318        24036 :                     charcnt = detzcode(up->tzhead.tzh_charcnt);
     319        24036 :         char const *p = up->buf + tzheadsize;
     320              : 
     321              :         /*
     322              :          * Although tzfile(5) currently requires typecnt to be nonzero,
     323              :          * support future formats that may allow zero typecnt in files that
     324              :          * have a TZ string and no transitions.
     325              :          */
     326        48072 :         if (!(0 <= leapcnt
     327        24036 :               && leapcnt <= (TZ_RUNTIME_LEAPS ? TZ_MAX_LEAPS : 0)
     328        24036 :               && 0 <= typecnt && typecnt <= TZ_MAX_TYPES
     329        24036 :               && 0 <= timecnt && timecnt <= TZ_MAX_TIMES
     330        24036 :               && 0 <= charcnt && charcnt <= TZ_MAX_CHARS
     331        24036 :               && 0 <= ttisstdcnt && ttisstdcnt <= TZ_MAX_TYPES
     332        24036 :               && 0 <= ttisutcnt && ttisutcnt <= TZ_MAX_TYPES))
     333            0 :             return EINVAL;
     334              :         datablock_size
     335        24036 :             = (timecnt * stored /* ats */
     336        24036 :                + timecnt        /* types */
     337        24036 :                + typecnt * 6    /* ttinfos */
     338        24036 :                + charcnt        /* chars */
     339        24036 :                + leapcnt * (stored + 4) /* lsinfos */
     340        24036 :                + ttisstdcnt     /* ttisstds */
     341              :                + ttisutcnt);    /* ttisuts */
     342        24036 :         if (nread < tzheadsize + datablock_size)
     343            0 :             return EINVAL;
     344        24036 :         if (skip_datablock)
     345        12018 :             p += datablock_size;
     346        12018 :         else if (!((ttisstdcnt == typecnt || ttisstdcnt == 0)
     347        12018 :                    && (ttisutcnt == typecnt || ttisutcnt == 0)))
     348            0 :             return EINVAL;
     349              :         else
     350              :         {
     351        12018 :             int_fast64_t prevtr = -1;
     352        12018 :             int_fast32_2s prevcorr = -1;
     353              : 
     354        12018 :             set_leapcount(sp, leapcnt);
     355        12018 :             sp->timecnt = timecnt;
     356        12018 :             sp->typecnt = typecnt;
     357        12018 :             sp->charcnt = charcnt;
     358              : 
     359              :             /*
     360              :              * Read transitions, discarding those out of pg_time_t range. But
     361              :              * pretend the last transition before TIME_T_MIN occurred at
     362              :              * TIME_T_MIN.
     363              :              */
     364        12018 :             timecnt = 0;
     365       893889 :             for (i = 0; i < sp->timecnt; ++i)
     366              :             {
     367       881871 :                 int_fast64_t at
     368       881871 :                 = stored == 4 ? detzcode(p) : detzcode64(p);
     369              : 
     370       881871 :                 sp->types[i] = at <= TIME_T_MAX;
     371       881871 :                 if (sp->types[i])
     372              :                 {
     373       881871 :                     pg_time_t   attime
     374              :                     = ((TYPE_SIGNED(pg_time_t) ? at < TIME_T_MIN : at < 0)
     375              :                        ? TIME_T_MIN : at);
     376              : 
     377       881871 :                     if (timecnt && attime <= sp->ats[timecnt - 1])
     378              :                     {
     379            0 :                         if (attime < sp->ats[timecnt - 1])
     380            0 :                             return EINVAL;
     381            0 :                         sp->types[i - 1] = 0;
     382            0 :                         timecnt--;
     383              :                     }
     384       881871 :                     sp->ats[timecnt++] = attime;
     385              :                 }
     386       881871 :                 p += stored;
     387              :             }
     388              : 
     389        12018 :             timecnt = 0;
     390       893889 :             for (i = 0; i < sp->timecnt; ++i)
     391              :             {
     392       881871 :                 unsigned char typ = *p++;
     393              : 
     394       881871 :                 if (sp->typecnt <= typ)
     395            0 :                     return EINVAL;
     396       881871 :                 if (sp->types[i])
     397       881871 :                     sp->types[timecnt++] = typ;
     398              :             }
     399        12018 :             sp->timecnt = timecnt;
     400        64331 :             for (i = 0; i < sp->typecnt; ++i)
     401              :             {
     402              :                 struct ttinfo *ttisp;
     403              :                 unsigned char isdst,
     404              :                             desigidx;
     405        52313 :                 int_fast32_2s utoff = detzcode(p);
     406              : 
     407              :                 /*
     408              :                  * Reject a UT offset equal to -2**31, as it might cause
     409              :                  * trouble both in this file and in callers. Also, it violates
     410              :                  * RFC 9636 section 3.2.
     411              :                  */
     412        52313 :                 if (utoff < -TWO_31_MINUS_1)
     413            0 :                     return EINVAL;
     414              : 
     415        52313 :                 ttisp = &sp->ttis[i];
     416        52313 :                 ttisp->tt_utoff = utoff;
     417        52313 :                 p += 4;
     418        52313 :                 isdst = *p++;
     419        52313 :                 if (!(isdst < 2))
     420            0 :                     return EINVAL;
     421        52313 :                 ttisp->tt_isdst = isdst;
     422        52313 :                 desigidx = *p++;
     423        52313 :                 if (!(desigidx < sp->charcnt))
     424            0 :                     return EINVAL;
     425        52313 :                 ttisp->tt_desigidx = desigidx;
     426              :             }
     427       217507 :             for (i = 0; i < sp->charcnt; ++i)
     428       205489 :                 sp->chars[i] = *p++;
     429              : 
     430              :             /*
     431              :              * Ensure '\0'-terminated, and make it safe to call ttunspecified
     432              :              * later.
     433              :              */
     434        12018 :             memset(&sp->chars[i], 0, CHARS_EXTRA);
     435              : 
     436              :             /* Read leap seconds, discarding those out of pg_time_t range.  */
     437        12018 :             leapcnt = 0;
     438        12018 :             for (i = 0; i < leapcount(sp); i++)
     439              :             {
     440            0 :                 int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
     441            0 :                 int_fast32_2s corr = detzcode(p + stored);
     442              : 
     443            0 :                 p += stored + 4;
     444              : 
     445              :                 /*
     446              :                  * Leap seconds cannot occur before the Epoch, or out of
     447              :                  * order.
     448              :                  */
     449            0 :                 if (tr <= prevtr)
     450            0 :                     return EINVAL;
     451              : 
     452              :                 /*
     453              :                  * To avoid other botches in this code, each leap second's
     454              :                  * correction must differ from the previous one's by 1 second
     455              :                  * or less, except that the first correction can be any value;
     456              :                  * these requirements are more generous than RFC 9636, to
     457              :                  * allow future RFC extensions.
     458              :                  */
     459            0 :                 if (!(i == 0
     460            0 :                       || (prevcorr < corr
     461            0 :                           ? corr == prevcorr + 1
     462              :                           : (corr == prevcorr
     463            0 :                              || corr == prevcorr - 1))))
     464            0 :                     return EINVAL;
     465            0 :                 prevtr = tr;
     466            0 :                 prevcorr = corr;
     467              : 
     468              :                 if (tr <= TIME_T_MAX)
     469              :                 {
     470              :                     struct lsinfo ls;
     471              : 
     472            0 :                     ls.ls_trans = tr;
     473            0 :                     ls.ls_corr = corr;
     474            0 :                     set_lsinfo(sp, leapcnt, ls);
     475            0 :                     leapcnt++;
     476              :                 }
     477              :             }
     478        12018 :             set_leapcount(sp, leapcnt);
     479              : 
     480        64331 :             for (i = 0; i < sp->typecnt; ++i)
     481              :             {
     482              :                 struct ttinfo *ttisp;
     483              : 
     484        52313 :                 ttisp = &sp->ttis[i];
     485        52313 :                 if (ttisstdcnt == 0)
     486        52313 :                     ttisp->tt_ttisstd = false;
     487              :                 else
     488              :                 {
     489            0 :                     if (*p != true && *p != false)
     490            0 :                         return EINVAL;
     491            0 :                     ttisp->tt_ttisstd = *p++;
     492              :                 }
     493              :             }
     494        64331 :             for (i = 0; i < sp->typecnt; ++i)
     495              :             {
     496              :                 struct ttinfo *ttisp;
     497              : 
     498        52313 :                 ttisp = &sp->ttis[i];
     499        52313 :                 if (ttisutcnt == 0)
     500        52313 :                     ttisp->tt_ttisut = false;
     501              :                 else
     502              :                 {
     503            0 :                     if (*p != true && *p != false)
     504            0 :                         return EINVAL;
     505            0 :                     ttisp->tt_ttisut = *p++;
     506              :                 }
     507              :             }
     508              :         }
     509              : 
     510        24036 :         nread -= p - up->buf;
     511        24036 :         memmove(up->buf, p, nread);
     512              : 
     513              :         /* If this is an old file, we're done.  */
     514        24036 :         if (!version)
     515            0 :             break;
     516              :     }
     517        12018 :     if ((tzloadflags & TZLOAD_TZSTRING) && nread > 2 &&
     518        12018 :         up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
     519        12018 :         sp->typecnt + 2 <= TZ_MAX_TYPES)
     520              :     {
     521        12018 :         struct state *ts = &lsp->u.st;
     522              : 
     523        12018 :         up->buf[nread - 1] = '\0';
     524        12018 :         if (tzparse(&up->buf[1], ts, sp))
     525              :         {
     526              : 
     527              :             /*
     528              :              * Attempt to reuse existing abbreviations. Without this,
     529              :              * America/Anchorage would consume 50 bytes for abbreviations, as
     530              :              * sp->charcnt equals 40 (for LMT AST AWT APT AHST AHDT YST AKDT
     531              :              * AKST) and ts->charcnt equals 10 (for AKST AKDT).  Reusing means
     532              :              * sp->charcnt can stay 40 in this example.
     533              :              */
     534        12018 :             int         gotabbr = 0;
     535        12018 :             int         charcnt = sp->charcnt;
     536              : 
     537        30726 :             for (i = 0; i < ts->typecnt; i++)
     538              :             {
     539        18708 :                 char       *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
     540              :                 int         j;
     541              : 
     542       157247 :                 for (j = 0; j < charcnt; j++)
     543       157187 :                     if (strcmp(sp->chars + j, tsabbr) == 0)
     544              :                     {
     545        18648 :                         ts->ttis[i].tt_desigidx = j;
     546        18648 :                         gotabbr++;
     547        18648 :                         break;
     548              :                     }
     549        18708 :                 if (!(j < charcnt))
     550              :                 {
     551           60 :                     int         tsabbrlen = strnlen(tsabbr, TZ_MAX_CHARS - j);
     552              : 
     553           60 :                     if (j + tsabbrlen < TZ_MAX_CHARS)
     554              :                     {
     555           60 :                         char       *cp = sp->chars + j;
     556              : 
     557           60 :                         memcpy(cp, tsabbr, tsabbrlen);
     558           60 :                         cp += tsabbrlen;
     559           60 :                         *cp = '\0';
     560           60 :                         charcnt = j + tsabbrlen + 1;
     561           60 :                         ts->ttis[i].tt_desigidx = j;
     562           60 :                         gotabbr++;
     563              :                     }
     564              :                 }
     565              :             }
     566        12018 :             if (gotabbr == ts->typecnt)
     567              :             {
     568        12018 :                 sp->charcnt = charcnt;
     569              : 
     570              :                 /*
     571              :                  * Ignore any trailing, no-op transitions generated by zic as
     572              :                  * they don't help here and can run afoul of bugs in zic 2016j
     573              :                  * or earlier.
     574              :                  */
     575        12018 :                 while (1 < sp->timecnt
     576        12366 :                        && (sp->types[sp->timecnt - 1]
     577        10299 :                            == sp->types[sp->timecnt - 2]))
     578          348 :                     sp->timecnt--;
     579              : 
     580        12018 :                 sp->goahead = ts->goahead;
     581              : 
     582      5390132 :                 for (i = 0; i < ts->timecnt; i++)
     583              :                 {
     584      5378114 :                     pg_time_t   t = ts->ats[i];
     585              : 
     586      5378114 :                     if (increment_overflow_time(&t, leapcorr(sp, t))
     587      5378114 :                         || (0 < sp->timecnt
     588      5378114 :                             && t <= sp->ats[sp->timecnt - 1]))
     589         6272 :                         continue;
     590      5371842 :                     if (TZ_MAX_TIMES <= sp->timecnt)
     591              :                     {
     592            0 :                         sp->goahead = false;
     593            0 :                         break;
     594              :                     }
     595      5371842 :                     sp->ats[sp->timecnt] = t;
     596      5371842 :                     sp->types[sp->timecnt] = (sp->typecnt
     597      5371842 :                                               + ts->types[i]);
     598      5371842 :                     sp->timecnt++;
     599              :                 }
     600        30726 :                 for (i = 0; i < ts->typecnt; i++)
     601        18708 :                     sp->ttis[sp->typecnt++] = ts->ttis[i];
     602              :             }
     603              :         }
     604              :     }
     605        12018 :     if (sp->typecnt == 0)
     606            0 :         return EINVAL;
     607              : 
     608        12018 :     return 0;
     609              : }
     610              : 
     611              : /*
     612              :  * Load tz data from the file named NAME into *SP.  Respect TZLOADFLAGS.
     613              :  * Return 0 on success, an errno value on failure.
     614              :  * PG: If "canonname" is not NULL, then on success the canonical spelling of
     615              :  * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
     616              :  */
     617              : static int
     618        12307 : tzload(char const *name, char *canonname, struct state *sp, char tzloadflags)
     619              : {
     620              :     /* PG: our version of tzloadbody never reallocates *lspp */
     621              :     union local_storage *lsp;
     622              :     union local_storage ls;
     623              : 
     624        12307 :     lsp = &ls;
     625        12307 :     return tzloadbody(name, canonname, sp, tzloadflags, &lsp);
     626              : }
     627              : 
     628              : static const int mon_lengths[2][MONSPERYEAR] = {
     629              :     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
     630              :     {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
     631              : };
     632              : 
     633              : static const int year_lengths[2] = {
     634              :     DAYSPERNYEAR, DAYSPERLYEAR
     635              : };
     636              : 
     637              : /* Is C an ASCII digit?  */
     638              : static bool
     639       193121 : is_digit(char c)
     640              : {
     641       193121 :     return '0' <= c && c <= '9';
     642              : }
     643              : 
     644              : /*
     645              :  * Given a pointer into a timezone string, scan until a character that is not
     646              :  * a valid character in a time zone abbreviation is found.
     647              :  * Return a pointer to that character.
     648              :  */
     649              : 
     650              : ATTRIBUTE_PURE_114833 static const char *
     651        17844 : getzname(const char *strp)
     652              : {
     653              :     char        c;
     654              : 
     655        73183 :     while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
     656              :            c != '+')
     657        55339 :         ++strp;
     658        17844 :     return strp;
     659              : }
     660              : 
     661              : /*
     662              :  * Given a pointer into an extended timezone string, scan until the ending
     663              :  * delimiter of the time zone abbreviation is located.
     664              :  * Return a pointer to the delimiter.
     665              :  *
     666              :  * As with getzname above, the legal character set is actually quite
     667              :  * restricted, with other characters producing undefined results.
     668              :  * We don't do any checking here; checking is done later in common-case code.
     669              :  */
     670              : 
     671              : ATTRIBUTE_PURE_114833 static const char *
     672         2671 : getqzname(const char *strp, const int delim)
     673              : {
     674              :     int         c;
     675              : 
     676        11076 :     while ((c = *strp) != '\0' && c != delim)
     677         8405 :         ++strp;
     678         2671 :     return strp;
     679              : }
     680              : 
     681              : /*
     682              :  * Given a pointer into a timezone string, extract a number from that string.
     683              :  * Check that the number is within a specified range; if it is not, return
     684              :  * NULL.
     685              :  * Otherwise, return a pointer to the first character not part of the number.
     686              :  */
     687              : 
     688              : static const char *
     689        55970 : getnum(const char *strp, int *const nump, const int min, const int max)
     690              : {
     691              :     char        c;
     692              :     int         num;
     693              : 
     694        55970 :     if (strp == NULL || !is_digit(c = *strp))
     695           68 :         return NULL;
     696        55902 :     num = 0;
     697              :     do
     698              :     {
     699        64040 :         num = num * 10 + (c - '0');
     700        64040 :         if (num > max)
     701            0 :             return NULL;        /* illegal value */
     702        64040 :         c = *++strp;
     703        64040 :     } while (is_digit(c));
     704        55902 :     if (num < min)
     705            0 :         return NULL;            /* illegal value */
     706        55902 :     *nump = num;
     707        55902 :     return strp;
     708              : }
     709              : 
     710              : /*
     711              :  * Given a pointer into a timezone string, extract a number of seconds,
     712              :  * in hh[:mm[:ss]] form, from the string.
     713              :  * If any error occurs, return NULL.
     714              :  * Otherwise, return a pointer to the first character not part of the number
     715              :  * of seconds.
     716              :  */
     717              : 
     718              : static const char *
     719        15386 : getsecs(const char *strp, int_fast32_t *const secsp)
     720              : {
     721              :     int         num;
     722        15386 :     int_fast32_t secsperhour = SECSPERHOUR;
     723              : 
     724              :     /*
     725              :      * 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-POSIX rules like
     726              :      * "M10.4.6/26", which does not conform to POSIX, but which specifies the
     727              :      * equivalent of "02:00 on the first Sunday on or after 23 Oct".
     728              :      */
     729        15386 :     strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
     730        15386 :     if (strp == NULL)
     731           68 :         return NULL;
     732        15318 :     *secsp = num * secsperhour;
     733        15318 :     if (*strp == ':')
     734              :     {
     735          366 :         ++strp;
     736          366 :         strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
     737          366 :         if (strp == NULL)
     738            0 :             return NULL;
     739          366 :         *secsp += num * SECSPERMIN;
     740          366 :         if (*strp == ':')
     741              :         {
     742            0 :             ++strp;
     743              :             /* 'SECSPERMIN' allows for leap seconds.  */
     744            0 :             strp = getnum(strp, &num, 0, SECSPERMIN);
     745            0 :             if (strp == NULL)
     746            0 :                 return NULL;
     747            0 :             *secsp += num;
     748              :         }
     749              :     }
     750        15318 :     return strp;
     751              : }
     752              : 
     753              : /*
     754              :  * Given a pointer into a timezone string, extract an offset, in
     755              :  * [+-]hh[:mm[:ss]] form, from the string.
     756              :  * If any error occurs, return NULL.
     757              :  * Otherwise, return a pointer to the first character not part of the time.
     758              :  */
     759              : 
     760              : static const char *
     761        15386 : getoffset(const char *strp, int_fast32_t *const offsetp)
     762              : {
     763        15386 :     bool        neg = false;
     764              : 
     765        15386 :     if (*strp == '-')
     766              :     {
     767         3387 :         neg = true;
     768         3387 :         ++strp;
     769              :     }
     770        11999 :     else if (*strp == '+')
     771           85 :         ++strp;
     772        15386 :     strp = getsecs(strp, offsetp);
     773        15386 :     if (strp == NULL)
     774           68 :         return NULL;            /* illegal time */
     775        15318 :     if (neg)
     776         3387 :         *offsetp = -*offsetp;
     777        15318 :     return strp;
     778              : }
     779              : 
     780              : /*
     781              :  * Given a pointer into a timezone string, extract a rule in the form
     782              :  * date[/time]. See POSIX Base Definitions section 8.3 variable TZ
     783              :  * for the format of "date" and "time".
     784              :  * If a valid rule is not found, return NULL.
     785              :  * Otherwise, return a pointer to the first character not part of the rule.
     786              :  */
     787              : 
     788              : static const char *
     789        13406 : getrule(const char *strp, struct rule *const rulep)
     790              : {
     791        13406 :     if (*strp == 'J')
     792              :     {
     793              :         /*
     794              :          * Julian day.
     795              :          */
     796            0 :         rulep->r_type = JULIAN_DAY;
     797            0 :         ++strp;
     798            0 :         strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
     799              :     }
     800        13406 :     else if (*strp == 'M')
     801              :     {
     802              :         /*
     803              :          * Month, week, day.
     804              :          */
     805        13406 :         rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
     806        13406 :         ++strp;
     807        13406 :         strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
     808        13406 :         if (strp == NULL)
     809            0 :             return NULL;
     810        13406 :         if (*strp++ != '.')
     811            0 :             return NULL;
     812        13406 :         strp = getnum(strp, &rulep->r_week, 1, 5);
     813        13406 :         if (strp == NULL)
     814            0 :             return NULL;
     815        13406 :         if (*strp++ != '.')
     816            0 :             return NULL;
     817        13406 :         strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
     818              :     }
     819            0 :     else if (is_digit(*strp))
     820              :     {
     821              :         /*
     822              :          * Day of year.
     823              :          */
     824            0 :         rulep->r_type = DAY_OF_YEAR;
     825            0 :         strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
     826              :     }
     827              :     else
     828            0 :         return NULL;            /* invalid format */
     829        13406 :     if (strp == NULL)
     830            0 :         return NULL;
     831        13406 :     if (*strp == '/')
     832              :     {
     833              :         /*
     834              :          * Time specified.
     835              :          */
     836         1520 :         ++strp;
     837         1520 :         strp = getoffset(strp, &rulep->r_time);
     838              :     }
     839              :     else
     840        11886 :         rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
     841        13406 :     return strp;
     842              : }
     843              : 
     844              : /*
     845              :  * Given a year, a rule, and the offset from UT at the time that rule takes
     846              :  * effect, calculate the year-relative time that rule takes effect.
     847              :  */
     848              : 
     849              : static int_fast32_t
     850      5389212 : transtime(const int year, const struct rule *const rulep,
     851              :           const int_fast32_t offset)
     852              : {
     853              :     bool        leapyear;
     854              :     int_fast32_t value;
     855              :     int         i;
     856              :     int         d,
     857              :                 m1,
     858              :                 yy0,
     859              :                 yy1,
     860              :                 yy2,
     861              :                 dow;
     862              : 
     863      5389212 :     leapyear = isleap(year);
     864      5389212 :     switch (rulep->r_type)
     865              :     {
     866              : 
     867            0 :         case JULIAN_DAY:
     868              : 
     869              :             /*
     870              :              * Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
     871              :              * years. In non-leap years, or if the day number is 59 or less,
     872              :              * just add SECSPERDAY times the day number-1 to the time of
     873              :              * January 1, midnight, to get the day.
     874              :              */
     875            0 :             value = (rulep->r_day - 1) * SECSPERDAY;
     876            0 :             if (leapyear && rulep->r_day >= 60)
     877            0 :                 value += SECSPERDAY;
     878            0 :             break;
     879              : 
     880            0 :         case DAY_OF_YEAR:
     881              : 
     882              :             /*
     883              :              * n - day of year. Just add SECSPERDAY times the day number to
     884              :              * the time of January 1, midnight, to get the day.
     885              :              */
     886            0 :             value = rulep->r_day * SECSPERDAY;
     887            0 :             break;
     888              : 
     889      5389212 :         case MONTH_NTH_DAY_OF_WEEK:
     890              : 
     891              :             /*
     892              :              * Mm.n.d - nth "dth day" of month m.
     893              :              */
     894              : 
     895              :             /*
     896              :              * Use Zeller's Congruence to get day-of-week of first day of
     897              :              * month.
     898              :              */
     899      5389212 :             m1 = (rulep->r_mon + 9) % 12 + 1;
     900      5389212 :             yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
     901      5389212 :             yy1 = yy0 / 100;
     902      5389212 :             yy2 = yy0 % 100;
     903      5389212 :             dow = ((26 * m1 - 2) / 10 +
     904      5389212 :                    1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
     905      5389212 :             if (dow < 0)
     906       970987 :                 dow += DAYSPERWEEK;
     907              : 
     908              :             /*
     909              :              * "dow" is the day-of-week of the first day of the month. Get the
     910              :              * day-of-month (zero-origin) of the first "dow" day of the month.
     911              :              */
     912      5389212 :             d = rulep->r_day - dow;
     913      5389212 :             if (d < 0)
     914      4554113 :                 d += DAYSPERWEEK;
     915     10075986 :             for (i = 1; i < rulep->r_week; ++i)
     916              :             {
     917      5088114 :                 if (d + DAYSPERWEEK >=
     918      5088114 :                     mon_lengths[leapyear][rulep->r_mon - 1])
     919       401340 :                     break;
     920      4686774 :                 d += DAYSPERWEEK;
     921              :             }
     922              : 
     923              :             /*
     924              :              * "d" is the day-of-month (zero-origin) of the day we want.
     925              :              */
     926      5389212 :             value = d * SECSPERDAY;
     927     37341378 :             for (i = 0; i < rulep->r_mon - 1; ++i)
     928     31952166 :                 value += mon_lengths[leapyear][i] * SECSPERDAY;
     929      5389212 :             break;
     930              : 
     931            0 :         default:
     932            0 :             unreachable();
     933              :     }
     934              : 
     935              :     /*
     936              :      * "value" is the year-relative time of 00:00:00 UT on the day in
     937              :      * question. To get the year-relative time of the specified local time on
     938              :      * that day, add the transition time and the current offset from UT.
     939              :      */
     940      5389212 :     return value + rulep->r_time + offset;
     941              : }
     942              : 
     943              : /*
     944              :  * Given a POSIX.1 proleptic TZ string, fill in the rule tables as
     945              :  * appropriate.
     946              :  */
     947              : 
     948              : static bool
     949        13812 : tzparse(const char *name, struct state *sp, struct state const *basep)
     950              : {
     951              :     const char *stdname;
     952        13812 :     const char *dstname = NULL;
     953              :     int_fast32_t stdoffset;
     954              :     int_fast32_t dstoffset;
     955              :     char       *cp;
     956              :     ptrdiff_t   stdlen,
     957              :                 dstlen,
     958              :                 charcnt;
     959        13812 :     pg_time_t   atlo = TIME_T_MIN,
     960        13812 :                 leaplo = TIME_T_MIN;
     961              : 
     962        13812 :     stdname = name;
     963        13812 :     if (*name == '<')
     964              :     {
     965         2509 :         name++;
     966         2509 :         stdname = name;
     967         2509 :         name = getqzname(name, '>');
     968         2509 :         if (*name != '>')
     969            0 :             return false;
     970         2509 :         stdlen = name - stdname;
     971         2509 :         name++;
     972              :     }
     973              :     else
     974              :     {
     975        11303 :         name = getzname(name);
     976        11303 :         stdlen = name - stdname;
     977              :     }
     978        13812 :     if (stdlen > TZNAME_MAXIMUM) /* allow empty STD abbrev, unlike IANA */
     979            0 :         return false;
     980        13812 :     name = getoffset(name, &stdoffset);
     981        13812 :     if (name == NULL)
     982           68 :         return false;
     983        13744 :     charcnt = stdlen + 1;
     984        13744 :     if (basep)
     985              :     {
     986        12018 :         if (0 < basep->timecnt)
     987        10411 :             atlo = basep->ats[basep->timecnt - 1];
     988        12018 :         set_leapcount(sp, leapcount(basep));
     989        12018 :         if (0 < leapcount(sp))
     990              :         {
     991              :             int         i;
     992              : 
     993            0 :             for (i = 0; i < leapcount(sp); i++)
     994            0 :                 set_lsinfo(sp, i, lsinfo(basep, i));
     995            0 :             leaplo = lsinfo(sp, leapcount(sp) - 1).ls_trans;
     996              :         }
     997              :     }
     998              :     else
     999         1726 :         set_leapcount(sp, 0);   /* So, we're off a little.  */
    1000        13744 :     sp->goback = sp->goahead = false;
    1001        13744 :     if (*name != '\0')
    1002              :     {
    1003              :         struct rule start,
    1004              :                     end;
    1005              :         int         year,
    1006              :                     yearbeg,
    1007              :                     yearlim,
    1008              :                     timecnt;
    1009              :         pg_time_t   janfirst;
    1010         6703 :         int_fast32_t janoffset = 0;
    1011              : 
    1012         6703 :         if (*name == '<')
    1013              :         {
    1014          162 :             dstname = ++name;
    1015          162 :             name = getqzname(name, '>');
    1016          162 :             if (*name != '>')
    1017            0 :                 return false;
    1018          162 :             dstlen = name - dstname;
    1019          162 :             name++;
    1020              :         }
    1021              :         else
    1022              :         {
    1023         6541 :             dstname = name;
    1024         6541 :             name = getzname(name);
    1025         6541 :             dstlen = name - dstname;    /* length of DST abbr. */
    1026              :         }
    1027         6703 :         if (!(0 < dstlen && dstlen <= TZNAME_MAXIMUM))
    1028            0 :             return false;
    1029         6703 :         charcnt += dstlen + 1;
    1030         6703 :         if (*name != '\0' && *name != ',' && *name != ';')
    1031              :         {
    1032           54 :             name = getoffset(name, &dstoffset);
    1033           54 :             if (name == NULL)
    1034            0 :                 return false;
    1035              :         }
    1036              :         else
    1037         6649 :             dstoffset = stdoffset - SECSPERHOUR;
    1038              : 
    1039         6703 :         if (*name == '\0')
    1040            4 :             name = TZDEFRULESTRING;
    1041         6703 :         if (!(*name == ',' || *name == ';'))
    1042            0 :             return false;
    1043              : 
    1044         6703 :         name = getrule(name + 1, &start);
    1045         6703 :         if (!name)
    1046            0 :             return false;
    1047         6703 :         if (*name++ != ',')
    1048            0 :             return false;
    1049         6703 :         name = getrule(name, &end);
    1050         6703 :         if (!name || *name)
    1051            0 :             return false;
    1052         6703 :         sp->typecnt = 2;     /* standard time and DST */
    1053              : 
    1054              :         /*
    1055              :          * Two transitions per year, from EPOCH_YEAR forward.
    1056              :          */
    1057         6703 :         init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
    1058         6703 :         init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
    1059         6703 :         timecnt = 0;
    1060         6703 :         janfirst = 0;
    1061         6703 :         yearbeg = EPOCH_YEAR;
    1062              : 
    1063              :         do
    1064              :         {
    1065         9290 :             int_fast32_t yearsecs
    1066         9290 :             = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
    1067         9290 :             pg_time_t   janfirst1 = janfirst;
    1068              : 
    1069         9290 :             yearbeg--;
    1070         9290 :             if (increment_overflow_time(&janfirst1, -yearsecs))
    1071              :             {
    1072            0 :                 janoffset = -yearsecs;
    1073            0 :                 break;
    1074              :             }
    1075         9290 :             janfirst = janfirst1;
    1076         9290 :         } while (atlo < janfirst
    1077         9290 :                  && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
    1078              : 
    1079              :         while (true)
    1080       251413 :         {
    1081       258116 :             int_fast32_t yearsecs
    1082       258116 :             = year_lengths[isleap(yearbeg)] * SECSPERDAY;
    1083       258116 :             int         yearbeg1 = yearbeg;
    1084       258116 :             pg_time_t   janfirst1 = janfirst;
    1085              : 
    1086       258116 :             if (increment_overflow_time(&janfirst1, yearsecs)
    1087       258116 :                 || increment_overflow(&yearbeg1, 1)
    1088       258116 :                 || atlo <= janfirst1)
    1089              :                 break;
    1090       251413 :             yearbeg = yearbeg1;
    1091       251413 :             janfirst = janfirst1;
    1092              :         }
    1093              : 
    1094         6703 :         yearlim = yearbeg;
    1095         6703 :         if (increment_overflow(&yearlim, years_of_observations))
    1096            0 :             yearlim = INT_MAX;
    1097      2701309 :         for (year = yearbeg; year < yearlim; year++)
    1098              :         {
    1099              :             int_fast32_t
    1100      2694606 :                         starttime = transtime(year, &start, stdoffset),
    1101      2694606 :                         endtime = transtime(year, &end, dstoffset),
    1102      2694606 :                         yearsecs = year_lengths[isleap(year)] * SECSPERDAY;
    1103      2694606 :             bool        reversed = endtime < starttime;
    1104              : 
    1105      2694606 :             if (reversed)
    1106              :             {
    1107       123012 :                 int_fast32_t swap = starttime;
    1108              : 
    1109       123012 :                 starttime = endtime;
    1110       123012 :                 endtime = swap;
    1111              :             }
    1112      2694606 :             if (reversed
    1113      2571594 :                 || (starttime < endtime
    1114      2571594 :                     && endtime - starttime < yearsecs))
    1115              :             {
    1116      2694606 :                 if (TZ_MAX_TIMES - 2 < timecnt)
    1117            0 :                     break;
    1118      2694606 :                 sp->ats[timecnt] = janfirst;
    1119      2694606 :                 if (!increment_overflow_time(&sp->ats[timecnt],
    1120              :                                              janoffset + starttime)
    1121      2694606 :                     && atlo <= sp->ats[timecnt])
    1122      2694148 :                     sp->types[timecnt++] = !reversed;
    1123      2694606 :                 sp->ats[timecnt] = janfirst;
    1124      2694606 :                 if (!increment_overflow_time(&sp->ats[timecnt],
    1125              :                                              janoffset + endtime)
    1126      2694606 :                     && atlo <= sp->ats[timecnt])
    1127              :                 {
    1128      2694418 :                     sp->types[timecnt++] = reversed;
    1129              :                 }
    1130              :             }
    1131      2694606 :             if (endtime < leaplo)
    1132              :             {
    1133            0 :                 yearlim = year;
    1134            0 :                 if (increment_overflow(&yearlim, years_of_observations))
    1135            0 :                     yearlim = INT_MAX;
    1136              :             }
    1137      2694606 :             if (increment_overflow_time(&janfirst, janoffset + yearsecs))
    1138            0 :                 break;
    1139      2694606 :             janoffset = 0;
    1140              :         }
    1141         6703 :         sp->timecnt = timecnt;
    1142         6703 :         if (!timecnt)
    1143              :         {
    1144            0 :             sp->ttis[0] = sp->ttis[1];
    1145            0 :             sp->typecnt = 1; /* Perpetual DST.  */
    1146              :         }
    1147         6703 :         else if (years_of_observations <= year - yearbeg)
    1148         6703 :             sp->goback = sp->goahead = true;
    1149              :     }
    1150              :     else
    1151              :     {
    1152         7041 :         dstlen = 0;
    1153         7041 :         sp->typecnt = 1;     /* only standard time */
    1154         7041 :         sp->timecnt = 0;
    1155         7041 :         init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
    1156              :     }
    1157        13744 :     sp->charcnt = charcnt;
    1158        13744 :     cp = sp->chars;
    1159        13744 :     memcpy(cp, stdname, stdlen);
    1160        13744 :     cp += stdlen;
    1161        13744 :     *cp++ = '\0';
    1162        13744 :     if (dstlen != 0)
    1163              :     {
    1164         6703 :         memcpy(cp, dstname, dstlen);
    1165         6703 :         cp += dstlen;
    1166         6703 :         *cp = '\0';
    1167              :     }
    1168        13744 :     return true;
    1169              : }
    1170              : 
    1171              : static void
    1172         1505 : gmtload(struct state *const sp)
    1173              : {
    1174              :     /* PG: for historical compatibility, use "GMT" not "UTC" as TZ abbrev */
    1175         1505 :     tzparse("GMT0", sp, NULL);
    1176         1505 : }
    1177              : 
    1178              : 
    1179              : /*
    1180              :  * The easy way to behave "as if no library function calls" localtime
    1181              :  * is to not call it, so we drop its guts into "localsub", which can be
    1182              :  * freely called. (And no, the PANS doesn't require the above behavior,
    1183              :  * but it *is* desirable.)
    1184              :  */
    1185              : static struct pg_tm *
    1186      1393138 : localsub(struct state const *sp, pg_time_t const *timep,
    1187              :          struct pg_tm *const tmp)
    1188              : {
    1189              :     const struct ttinfo *ttisp;
    1190              :     int         i;
    1191              :     struct pg_tm *result;
    1192      1393138 :     const pg_time_t t = *timep;
    1193              : 
    1194      1393138 :     if (sp == NULL)
    1195            0 :         return gmtsub(timep, 0, tmp);
    1196      1393138 :     if ((sp->goback && t < sp->ats[0]) ||
    1197      1393138 :         (sp->goahead && t > sp->ats[sp->timecnt - 1]))
    1198              :     {
    1199              :         pg_time_t   newt;
    1200              :         pg_time_t   seconds;
    1201              :         pg_time_t   years;
    1202              : 
    1203           44 :         if (t < sp->ats[0])
    1204            0 :             seconds = sp->ats[0] - t;
    1205              :         else
    1206           44 :             seconds = t - sp->ats[sp->timecnt - 1];
    1207           44 :         --seconds;
    1208              : 
    1209              :         /*
    1210              :          * Beware integer overflow, as SECONDS might be close to the maximum
    1211              :          * pg_time_t.
    1212              :          */
    1213           44 :         years = seconds / SECSPERREPEAT * YEARSPERREPEAT;
    1214           44 :         seconds = years * AVGSECSPERYEAR;
    1215           44 :         years += YEARSPERREPEAT;
    1216           44 :         if (t < sp->ats[0])
    1217            0 :             newt = t + seconds + SECSPERREPEAT;
    1218              :         else
    1219           44 :             newt = t - seconds - SECSPERREPEAT;
    1220              : 
    1221           44 :         if (newt < sp->ats[0] ||
    1222           44 :             newt > sp->ats[sp->timecnt - 1])
    1223            0 :             return NULL;        /* "cannot happen" */
    1224           44 :         result = localsub(sp, &newt, tmp);
    1225           44 :         if (result)
    1226              :         {
    1227              : #if defined ckd_add && defined ckd_sub
    1228           88 :             if (t < sp->ats[0]
    1229            0 :                 ? ckd_sub(&result->tm_year,
    1230              :                           result->tm_year, years)
    1231           44 :                 : ckd_add(&result->tm_year,
    1232              :                           result->tm_year, years))
    1233            0 :                 return NULL;
    1234              : #else
    1235              :             int_fast64_t newy;
    1236              : 
    1237              :             newy = result->tm_year;
    1238              :             if (t < sp->ats[0])
    1239              :                 newy -= years;
    1240              :             else
    1241              :                 newy += years;
    1242              :             if (!(INT_MIN <= newy && newy <= INT_MAX))
    1243              :                 return NULL;
    1244              :             result->tm_year = newy;
    1245              : #endif
    1246              :         }
    1247           44 :         return result;
    1248              :     }
    1249      1393094 :     if (sp->timecnt == 0 || t < sp->ats[0])
    1250              :     {
    1251      1313041 :         i = 0;
    1252              :     }
    1253              :     else
    1254              :     {
    1255        80053 :         int         lo = 1;
    1256        80053 :         int         hi = sp->timecnt;
    1257              : 
    1258       826058 :         while (lo < hi)
    1259              :         {
    1260       746005 :             int         mid = (lo + hi) >> 1;
    1261              : 
    1262       746005 :             if (t < sp->ats[mid])
    1263       432358 :                 hi = mid;
    1264              :             else
    1265       313647 :                 lo = mid + 1;
    1266              :         }
    1267        80053 :         i = sp->types[lo - 1];
    1268              :     }
    1269      1393094 :     ttisp = &sp->ttis[i];
    1270              : 
    1271              :     /*
    1272              :      * To get (wrong) behavior that's compatible with System V Release 2.0
    1273              :      * you'd replace the statement below with t += ttisp->tt_utoff;
    1274              :      * timesub(&t, 0, sp, tmp);
    1275              :      */
    1276      1393094 :     result = timesub(&t, ttisp->tt_utoff, sp, tmp);
    1277      1393094 :     if (result)
    1278              :     {
    1279      1393094 :         result->tm_isdst = ttisp->tt_isdst;
    1280              : #ifdef TM_ZONE
    1281      1393094 :         result->TM_ZONE = UNCONST(&sp->chars[ttisp->tt_desigidx]);
    1282              : #endif
    1283              :     }
    1284      1393094 :     return result;
    1285              : }
    1286              : 
    1287              : 
    1288              : struct pg_tm *
    1289      1393094 : pg_localtime(const pg_time_t *timep, const pg_tz *tz)
    1290              : {
    1291      1393094 :     return localsub(&tz->state, timep, &tm);
    1292              : }
    1293              : 
    1294              : 
    1295              : /*
    1296              :  * gmtsub is to gmtime as localsub is to localtime.
    1297              :  *
    1298              :  * PG: except we have a private "struct state" for GMT, so no sp is passed in.
    1299              :  */
    1300              : 
    1301              : static struct pg_tm *
    1302       199778 : gmtsub(pg_time_t const *timep,
    1303              :        int_fast32_t offset, struct pg_tm *tmp)
    1304              : {
    1305              :     struct pg_tm *result;
    1306              : 
    1307              :     /* GMT timezone state data is kept here */
    1308              :     static struct state *gmtptr = NULL;
    1309              : 
    1310       199778 :     if (gmtptr == NULL)
    1311              :     {
    1312              :         /* Allocate on first use */
    1313          207 :         gmtptr = (struct state *) malloc(sizeof(struct state));
    1314          207 :         if (gmtptr == NULL)
    1315            0 :             return NULL;        /* errno should be set by malloc */
    1316          207 :         gmtload(gmtptr);
    1317              :     }
    1318              : 
    1319       199778 :     result = timesub(timep, offset, gmtptr, tmp);
    1320              : #ifdef TM_ZONE
    1321              : 
    1322              :     /*
    1323              :      * Could get fancy here and deliver something such as "+xx" or "-xx" if
    1324              :      * offset is non-zero, but this is no time for a treasure hunt.
    1325              :      */
    1326       199778 :     tmp->TM_ZONE = UNCONST(offset ? wildabbr
    1327              :                            : gmtptr->chars);
    1328              : #endif                          /* defined TM_ZONE */
    1329       199778 :     return result;
    1330              : }
    1331              : 
    1332              : struct pg_tm *
    1333       199778 : pg_gmtime(const pg_time_t *timep)
    1334              : {
    1335       199778 :     return gmtsub(timep, 0, &tm);
    1336              : }
    1337              : 
    1338              : /*
    1339              :  * Return the number of leap years through the end of the given year
    1340              :  * where, to make the math easy, the answer for year zero is defined as zero.
    1341              :  */
    1342              : 
    1343              : static pg_time_t
    1344      6342114 : leaps_thru_end_of_nonneg(pg_time_t y)
    1345              : {
    1346      6342114 :     return y / 4 - y / 100 + y / 400;
    1347              : }
    1348              : 
    1349              : static pg_time_t
    1350      6342114 : leaps_thru_end_of(pg_time_t y)
    1351              : {
    1352              :     return (y < 0
    1353         1496 :             ? -1 - leaps_thru_end_of_nonneg(-1 - y)
    1354      6343610 :             : leaps_thru_end_of_nonneg(y));
    1355              : }
    1356              : 
    1357              : static struct pg_tm *
    1358      1592872 : timesub(const pg_time_t *timep, int_fast32_t offset,
    1359              :         const struct state *sp, struct pg_tm *tmp)
    1360              : {
    1361              :     pg_time_t   tdays;
    1362              :     const int  *ip;
    1363              :     int_fast32_2s corr;
    1364              :     int         i;
    1365              :     int_fast32_t idays,
    1366              :                 rem,
    1367              :                 dayoff,
    1368              :                 dayrem;
    1369              :     pg_time_t   y;
    1370              : 
    1371              :     /*
    1372              :      * If less than SECSPERMIN, the number of seconds since the most recent
    1373              :      * positive leap second; otherwise, do not add 1 to localtime tm_sec
    1374              :      * because of leap seconds.
    1375              :      */
    1376      1592872 :     pg_time_t   secs_since_posleap = SECSPERMIN;
    1377              : 
    1378      1592872 :     corr = 0;
    1379      1592872 :     i = sp ? leapcount(sp) : 0;
    1380      1592872 :     while (--i >= 0)
    1381              :     {
    1382            0 :         struct lsinfo ls = lsinfo(sp, i);
    1383              : 
    1384            0 :         if (ls.ls_trans <= *timep)
    1385              :         {
    1386            0 :             corr = ls.ls_corr;
    1387            0 :             if ((i == 0 ? 0 : lsinfo(sp, i - 1).ls_corr) < corr)
    1388            0 :                 secs_since_posleap = *timep - ls.ls_trans;
    1389            0 :             break;
    1390              :         }
    1391              :     }
    1392              : 
    1393              :     /*
    1394              :      * Calculate the year, avoiding integer overflow even if pg_time_t is
    1395              :      * unsigned.
    1396              :      */
    1397      1592872 :     tdays = *timep / SECSPERDAY;
    1398      1592872 :     rem = *timep % SECSPERDAY;
    1399      1592872 :     rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
    1400      1592872 :     dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
    1401      1592872 :     rem %= SECSPERDAY;
    1402              : 
    1403              :     /*
    1404              :      * y = (EPOCH_YEAR + floor((tdays + dayoff) / DAYSPERREPEAT) *
    1405              :      * YEARSPERREPEAT), sans overflow.  But calculate against 1570 (EPOCH_YEAR
    1406              :      * - YEARSPERREPEAT) instead of against 1970 so that things work for
    1407              :      * localtime values before 1970 when pg_time_t is unsigned.
    1408              :      */
    1409      1592872 :     dayrem = tdays % DAYSPERREPEAT;
    1410      1592872 :     dayrem += dayoff % DAYSPERREPEAT;
    1411      1592872 :     y = (EPOCH_YEAR - YEARSPERREPEAT
    1412      1592872 :          + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
    1413      1592872 :              - ((dayrem % DAYSPERREPEAT) < 0)
    1414      1592872 :              + tdays / DAYSPERREPEAT)
    1415              :             * YEARSPERREPEAT));
    1416              :     /* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow.  */
    1417      1592872 :     idays = tdays % DAYSPERREPEAT;
    1418      1592872 :     idays += dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT;
    1419      1592872 :     idays %= DAYSPERREPEAT;
    1420              :     /* Increase Y and decrease IDAYS until IDAYS is in range for Y.  */
    1421      3171057 :     while (year_lengths[isleap(y)] <= idays)
    1422              :     {
    1423      1578185 :         int         tdelta = idays / DAYSPERLYEAR;
    1424      1578185 :         int_fast32_t ydelta = tdelta + !tdelta;
    1425      1578185 :         pg_time_t   newy = y + ydelta;
    1426              :         int         leapdays;
    1427              : 
    1428      1578185 :         leapdays = leaps_thru_end_of(newy - 1) -
    1429      1578185 :             leaps_thru_end_of(y - 1);
    1430      1578185 :         idays -= ydelta * DAYSPERNYEAR;
    1431      1578185 :         idays -= leapdays;
    1432      1578185 :         y = newy;
    1433              :     }
    1434              : 
    1435              : #ifdef ckd_add
    1436      1592872 :     if (ckd_add(&tmp->tm_year, y, -TM_YEAR_BASE))
    1437              :     {
    1438            0 :         errno = EOVERFLOW;
    1439            0 :         return NULL;
    1440              :     }
    1441              : #else
    1442              :     if (!TYPE_SIGNED(pg_time_t) && y < TM_YEAR_BASE)
    1443              :     {
    1444              :         int         signed_y = y;
    1445              : 
    1446              :         tmp->tm_year = signed_y - TM_YEAR_BASE;
    1447              :     }
    1448              :     else if ((!TYPE_SIGNED(pg_time_t) || INT_MIN + TM_YEAR_BASE <= y)
    1449              :              && y - TM_YEAR_BASE <= INT_MAX)
    1450              :         tmp->tm_year = y - TM_YEAR_BASE;
    1451              :     else
    1452              :     {
    1453              :         errno = EOVERFLOW;
    1454              :         return NULL;
    1455              :     }
    1456              : #endif
    1457      1592872 :     tmp->tm_yday = idays;
    1458              : 
    1459              :     /*
    1460              :      * The "extra" mods below avoid overflow problems.
    1461              :      */
    1462      1592872 :     tmp->tm_wday = (TM_WDAY_BASE
    1463      1592872 :                     + ((tmp->tm_year % DAYSPERWEEK)
    1464      1592872 :                        * (DAYSPERNYEAR % DAYSPERWEEK))
    1465      1592872 :                     + leaps_thru_end_of(y - 1)
    1466      1592872 :                     - leaps_thru_end_of(TM_YEAR_BASE - 1)
    1467      1592872 :                     + idays);
    1468      1592872 :     tmp->tm_wday %= DAYSPERWEEK;
    1469      1592872 :     if (tmp->tm_wday < 0)
    1470         1093 :         tmp->tm_wday += DAYSPERWEEK;
    1471      1592872 :     tmp->tm_hour = rem / SECSPERHOUR;
    1472      1592872 :     rem %= SECSPERHOUR;
    1473      1592872 :     tmp->tm_min = rem / SECSPERMIN;
    1474      1592872 :     tmp->tm_sec = rem % SECSPERMIN;
    1475              : 
    1476              :     /*
    1477              :      * Use "... ??:??:60" at the end of the localtime minute containing the
    1478              :      * second just before the positive leap second.
    1479              :      */
    1480      1592872 :     tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
    1481              : 
    1482      1592872 :     ip = mon_lengths[isleap(y)];
    1483     10743466 :     for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
    1484      9150594 :         idays -= ip[tmp->tm_mon];
    1485      1592872 :     tmp->tm_mday = idays + 1;
    1486      1592872 :     tmp->tm_isdst = 0;
    1487              : #ifdef TM_GMTOFF
    1488      1592872 :     tmp->TM_GMTOFF = offset;
    1489              : #endif                          /* defined TM_GMTOFF */
    1490      1592872 :     return tmp;
    1491              : }
    1492              : 
    1493              : /*
    1494              :  * Adapted from code provided by Robert Elz, who writes:
    1495              :  *  The "best" way to do mktime I think is based on an idea of Bob
    1496              :  *  Kridle's (so its said...) from a long time ago.
    1497              :  *  It does a binary search of the pg_time_t space. Since pg_time_t's are
    1498              :  *  just 32 bits, its a max of 32 iterations (even at 64 bits it
    1499              :  *  would still be very reasonable).
    1500              :  */
    1501              : 
    1502              : #ifndef WRONG
    1503              : #define WRONG (-1)
    1504              : #endif                          /* !defined WRONG */
    1505              : 
    1506              : /*
    1507              :  * Normalize logic courtesy Paul Eggert.
    1508              :  */
    1509              : 
    1510              : static bool
    1511       264819 : increment_overflow(int *ip, int j)
    1512              : {
    1513              : #ifdef ckd_add
    1514       264819 :     return ckd_add(ip, *ip, j);
    1515              : #else
    1516              :     int const   i = *ip;
    1517              : 
    1518              :     /*----------
    1519              :      * If i >= 0 there can only be overflow if i + j > INT_MAX
    1520              :      * or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
    1521              :      * If i < 0 there can only be overflow if i + j < INT_MIN
    1522              :      * or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
    1523              :      *----------
    1524              :      */
    1525              :     if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
    1526              :         return true;
    1527              :     *ip += j;
    1528              :     return false;
    1529              : #endif
    1530              : }
    1531              : 
    1532              : static bool
    1533     13729338 : increment_overflow_time(pg_time_t *tp, int_fast32_2s j)
    1534              : {
    1535              : #ifdef ckd_add
    1536     13729338 :     return ckd_add(tp, *tp, j);
    1537              : #else
    1538              :     /*----------
    1539              :      * This is like
    1540              :      * 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
    1541              :      * except that it does the right thing even if *tp + j would overflow.
    1542              :      *----------
    1543              :      */
    1544              :     if (!(j < 0
    1545              :           ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
    1546              :           : *tp <= TIME_T_MAX - j))
    1547              :         return true;
    1548              :     *tp += j;
    1549              :     return false;
    1550              : #endif
    1551              : }
    1552              : 
    1553              : static int_fast32_2s
    1554      5378114 : leapcorr(struct state const *sp, pg_time_t t)
    1555              : {
    1556              :     int         i;
    1557              : 
    1558      5378114 :     i = leapcount(sp);
    1559      5378114 :     while (--i >= 0)
    1560              :     {
    1561            0 :         struct lsinfo ls = lsinfo(sp, i);
    1562              : 
    1563            0 :         if (ls.ls_trans <= t)
    1564            0 :             return ls.ls_corr;
    1565              :     }
    1566      5378114 :     return 0;
    1567              : }
    1568              : 
    1569              : /*
    1570              :  * Postgres-specific functions begin here.
    1571              :  */
    1572              : 
    1573              : /*
    1574              :  * Load the definition of the given time zone name into *sp.
    1575              :  * Return true if successful, false if not.
    1576              :  * If "canonname" is not NULL, then on success the canonical spelling of
    1577              :  * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
    1578              :  *
    1579              :  * "GMT" is always interpreted as the gmtload() definition, without attempting
    1580              :  * to load a definition from the filesystem.  This has a number of benefits:
    1581              :  * 1. It's guaranteed to succeed, so we don't have the failure mode wherein
    1582              :  * the bootstrap default timezone setting doesn't work (as could happen if
    1583              :  * the OS attempts to supply a leap-second-aware version of "GMT").
    1584              :  * 2. Because we aren't accessing the filesystem, we can safely initialize
    1585              :  * the "GMT" zone definition before my_exec_path is known.
    1586              :  * 3. It's quick enough that we don't waste much time when the bootstrap
    1587              :  * default timezone setting is later overridden from postgresql.conf.
    1588              :  */
    1589              : bool
    1590        13605 : pg_tzload(const char *name, char *canonname, struct state *sp)
    1591              : {
    1592        13605 :     if (strcmp(name, "GMT") == 0)
    1593              :     {
    1594         1298 :         gmtload(sp);
    1595              :         /* Use given name as canonical */
    1596         1298 :         if (canonname)
    1597         1288 :             strcpy(canonname, name);
    1598              :     }
    1599        12307 :     else if (tzload(name, canonname, sp, TZLOAD_TZSTRING) != 0)
    1600              :     {
    1601          289 :         if (name[0] == ':' || !tzparse(name, sp, NULL))
    1602              :         {
    1603              :             /* Unknown timezone. Fail our call instead of loading GMT! */
    1604           68 :             return false;
    1605              :         }
    1606              :         /* For POSIX timezone specs, use given name as canonical */
    1607          221 :         if (canonname)
    1608          221 :             strcpy(canonname, name);
    1609              :     }
    1610        13537 :     return true;
    1611              : }
    1612              : 
    1613              : /*
    1614              :  * Find the next DST transition time in the given zone after the given time
    1615              :  *
    1616              :  * *timep and *tz are input arguments, the other parameters are output values.
    1617              :  *
    1618              :  * When the function result is 1, *boundary is set to the pg_time_t
    1619              :  * representation of the next DST transition time after *timep,
    1620              :  * *before_gmtoff and *before_isdst are set to the GMT offset and isdst
    1621              :  * state prevailing just before that boundary (in particular, the state
    1622              :  * prevailing at *timep), and *after_gmtoff and *after_isdst are set to
    1623              :  * the state prevailing just after that boundary.
    1624              :  *
    1625              :  * When the function result is 0, there is no known DST transition
    1626              :  * after *timep, but *before_gmtoff and *before_isdst indicate the GMT
    1627              :  * offset and isdst state prevailing at *timep.  (This would occur in
    1628              :  * DST-less time zones, or if a zone has permanently ceased using DST.)
    1629              :  *
    1630              :  * A function result of -1 indicates failure (this case does not actually
    1631              :  * occur in our current implementation).
    1632              :  */
    1633              : int
    1634       110386 : pg_next_dst_boundary(const pg_time_t *timep,
    1635              :                      long int *before_gmtoff,
    1636              :                      int *before_isdst,
    1637              :                      pg_time_t *boundary,
    1638              :                      long int *after_gmtoff,
    1639              :                      int *after_isdst,
    1640              :                      const pg_tz *tz)
    1641              : {
    1642              :     const struct state *sp;
    1643              :     const struct ttinfo *ttisp;
    1644              :     int         i;
    1645              :     int         j;
    1646       110386 :     const pg_time_t t = *timep;
    1647              : 
    1648       110386 :     sp = &tz->state;
    1649       110386 :     if (sp->timecnt == 0)
    1650              :     {
    1651              :         /* non-DST zone, use the defaulttype (now always 0) */
    1652         2631 :         ttisp = &sp->ttis[0];
    1653         2631 :         *before_gmtoff = ttisp->tt_utoff;
    1654         2631 :         *before_isdst = ttisp->tt_isdst;
    1655         2631 :         return 0;
    1656              :     }
    1657       107755 :     if ((sp->goback && t < sp->ats[0]) ||
    1658       107755 :         (sp->goahead && t > sp->ats[sp->timecnt - 1]))
    1659              :     {
    1660              :         /* For values outside the transition table, extrapolate */
    1661        34052 :         pg_time_t   newt = t;
    1662              :         pg_time_t   seconds;
    1663              :         pg_time_t   tcycles;
    1664              :         int64       icycles;
    1665              :         int         result;
    1666              : 
    1667        34052 :         if (t < sp->ats[0])
    1668            0 :             seconds = sp->ats[0] - t;
    1669              :         else
    1670        34052 :             seconds = t - sp->ats[sp->timecnt - 1];
    1671        34052 :         --seconds;
    1672        34052 :         tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
    1673        34052 :         ++tcycles;
    1674        34052 :         icycles = tcycles;
    1675        34052 :         if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
    1676            0 :             return -1;
    1677        34052 :         seconds = icycles;
    1678        34052 :         seconds *= YEARSPERREPEAT;
    1679        34052 :         seconds *= AVGSECSPERYEAR;
    1680        34052 :         if (t < sp->ats[0])
    1681            0 :             newt += seconds;
    1682              :         else
    1683        34052 :             newt -= seconds;
    1684        34052 :         if (newt < sp->ats[0] ||
    1685        34052 :             newt > sp->ats[sp->timecnt - 1])
    1686            0 :             return -1;          /* "cannot happen" */
    1687              : 
    1688        34052 :         result = pg_next_dst_boundary(&newt, before_gmtoff,
    1689              :                                       before_isdst,
    1690              :                                       boundary,
    1691              :                                       after_gmtoff,
    1692              :                                       after_isdst,
    1693              :                                       tz);
    1694        34052 :         if (t < sp->ats[0])
    1695            0 :             *boundary -= seconds;
    1696              :         else
    1697        34052 :             *boundary += seconds;
    1698        34052 :         return result;
    1699              :     }
    1700              : 
    1701        73703 :     if (t >= sp->ats[sp->timecnt - 1])
    1702              :     {
    1703              :         /* No known transition > t, so use last known segment's type */
    1704          720 :         i = sp->types[sp->timecnt - 1];
    1705          720 :         ttisp = &sp->ttis[i];
    1706          720 :         *before_gmtoff = ttisp->tt_utoff;
    1707          720 :         *before_isdst = ttisp->tt_isdst;
    1708          720 :         return 0;
    1709              :     }
    1710        72983 :     if (t < sp->ats[0])
    1711              :     {
    1712              :         /* For "before", use the defaulttype (now always 0) */
    1713          380 :         ttisp = &sp->ttis[0];
    1714          380 :         *before_gmtoff = ttisp->tt_utoff;
    1715          380 :         *before_isdst = ttisp->tt_isdst;
    1716          380 :         *boundary = sp->ats[0];
    1717              :         /* And for "after", use the first segment's type */
    1718          380 :         i = sp->types[0];
    1719          380 :         ttisp = &sp->ttis[i];
    1720          380 :         *after_gmtoff = ttisp->tt_utoff;
    1721          380 :         *after_isdst = ttisp->tt_isdst;
    1722          380 :         return 1;
    1723              :     }
    1724              :     /* Else search to find the boundary following t */
    1725              :     {
    1726        72603 :         int         lo = 1;
    1727        72603 :         int         hi = sp->timecnt - 1;
    1728              : 
    1729       790392 :         while (lo < hi)
    1730              :         {
    1731       717789 :             int         mid = (lo + hi) >> 1;
    1732              : 
    1733       717789 :             if (t < sp->ats[mid])
    1734       406879 :                 hi = mid;
    1735              :             else
    1736       310910 :                 lo = mid + 1;
    1737              :         }
    1738        72603 :         i = lo;
    1739              :     }
    1740        72603 :     j = sp->types[i - 1];
    1741        72603 :     ttisp = &sp->ttis[j];
    1742        72603 :     *before_gmtoff = ttisp->tt_utoff;
    1743        72603 :     *before_isdst = ttisp->tt_isdst;
    1744        72603 :     *boundary = sp->ats[i];
    1745        72603 :     j = sp->types[i];
    1746        72603 :     ttisp = &sp->ttis[j];
    1747        72603 :     *after_gmtoff = ttisp->tt_utoff;
    1748        72603 :     *after_isdst = ttisp->tt_isdst;
    1749        72603 :     return 1;
    1750              : }
    1751              : 
    1752              : /*
    1753              :  * Identify a timezone abbreviation's meaning in the given zone
    1754              :  *
    1755              :  * Determine the GMT offset and DST flag associated with the abbreviation.
    1756              :  * This is generally used only when the abbreviation has actually changed
    1757              :  * meaning over time; therefore, we also take a UTC cutoff time, and return
    1758              :  * the meaning in use at or most recently before that time, or the meaning
    1759              :  * in first use after that time if the abbrev was never used before that.
    1760              :  *
    1761              :  * On success, returns true and sets *gmtoff and *isdst.  If the abbreviation
    1762              :  * was never used at all in this zone, returns false.
    1763              :  *
    1764              :  * Note: abbrev is matched case-sensitively; it should be all-upper-case.
    1765              :  */
    1766              : bool
    1767         1134 : pg_interpret_timezone_abbrev(const char *abbrev,
    1768              :                              const pg_time_t *timep,
    1769              :                              long int *gmtoff,
    1770              :                              int *isdst,
    1771              :                              const pg_tz *tz)
    1772              : {
    1773              :     const struct state *sp;
    1774              :     const char *abbrs;
    1775              :     const struct ttinfo *ttisp;
    1776              :     int         abbrind;
    1777              :     int         cutoff;
    1778              :     int         i;
    1779         1134 :     const pg_time_t t = *timep;
    1780              : 
    1781         1134 :     sp = &tz->state;
    1782              : 
    1783              :     /*
    1784              :      * Locate the abbreviation in the zone's abbreviation list.  We assume
    1785              :      * there are not duplicates in the list.
    1786              :      */
    1787         1134 :     abbrs = sp->chars;
    1788         1134 :     abbrind = 0;
    1789         5872 :     while (abbrind < sp->charcnt)
    1790              :     {
    1791         5092 :         if (strcmp(abbrev, abbrs + abbrind) == 0)
    1792          354 :             break;
    1793        19598 :         while (abbrs[abbrind] != '\0')
    1794        14860 :             abbrind++;
    1795         4738 :         abbrind++;
    1796              :     }
    1797         1134 :     if (abbrind >= sp->charcnt)
    1798          780 :         return false;           /* not there! */
    1799              : 
    1800              :     /*
    1801              :      * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
    1802              :      * (goback/goahead zones).  Finding the newest or oldest meaning of the
    1803              :      * abbreviation should get us what we want, since extrapolation would just
    1804              :      * be repeating the newest or oldest meanings.
    1805              :      *
    1806              :      * Use binary search to locate the first transition > cutoff time.  (Note
    1807              :      * that sp->timecnt could be zero, in which case this loop does nothing
    1808              :      * and only the defaulttype entry will be checked.)
    1809              :      */
    1810              :     {
    1811          354 :         int         lo = 0;
    1812          354 :         int         hi = sp->timecnt;
    1813              : 
    1814         3038 :         while (lo < hi)
    1815              :         {
    1816         2684 :             int         mid = (lo + hi) >> 1;
    1817              : 
    1818         2684 :             if (t < sp->ats[mid])
    1819          992 :                 hi = mid;
    1820              :             else
    1821         1692 :                 lo = mid + 1;
    1822              :         }
    1823          354 :         cutoff = lo;
    1824              :     }
    1825              : 
    1826              :     /*
    1827              :      * Scan backwards to find the latest interval using the given abbrev
    1828              :      * before the cutoff time.
    1829              :      */
    1830        13710 :     for (i = cutoff - 1; i >= 0; i--)
    1831              :     {
    1832        13682 :         ttisp = &sp->ttis[sp->types[i]];
    1833        13682 :         if (ttisp->tt_desigidx == abbrind)
    1834              :         {
    1835          326 :             *gmtoff = ttisp->tt_utoff;
    1836          326 :             *isdst = ttisp->tt_isdst;
    1837          326 :             return true;
    1838              :         }
    1839              :     }
    1840              : 
    1841              :     /*
    1842              :      * Not found yet; check the defaulttype, which is notionally the era
    1843              :      * before any of the entries in sp->types[].
    1844              :      */
    1845           28 :     ttisp = &sp->ttis[0];
    1846           28 :     if (ttisp->tt_desigidx == abbrind)
    1847              :     {
    1848           28 :         *gmtoff = ttisp->tt_utoff;
    1849           28 :         *isdst = ttisp->tt_isdst;
    1850           28 :         return true;
    1851              :     }
    1852              : 
    1853              :     /*
    1854              :      * Not there, so scan forwards to find the first one after the cutoff.
    1855              :      */
    1856            0 :     for (i = cutoff; i < sp->timecnt; i++)
    1857              :     {
    1858            0 :         ttisp = &sp->ttis[sp->types[i]];
    1859            0 :         if (ttisp->tt_desigidx == abbrind)
    1860              :         {
    1861            0 :             *gmtoff = ttisp->tt_utoff;
    1862            0 :             *isdst = ttisp->tt_isdst;
    1863            0 :             return true;
    1864              :         }
    1865              :     }
    1866              : 
    1867            0 :     return false;               /* hm, not actually used in any interval? */
    1868              : }
    1869              : 
    1870              : /*
    1871              :  * Detect whether a timezone abbreviation is defined within the given zone.
    1872              :  *
    1873              :  * This is similar to pg_interpret_timezone_abbrev() but is not concerned
    1874              :  * with a specific point in time.  We want to know if the abbreviation is
    1875              :  * known at all, and if so whether it has one meaning or several.
    1876              :  *
    1877              :  * Returns true if the abbreviation is known, false if not.
    1878              :  * If the abbreviation is known and has a single meaning (only one value
    1879              :  * of gmtoff/isdst), sets *isfixed = true and sets *gmtoff and *isdst.
    1880              :  * If there are multiple meanings, sets *isfixed = false.
    1881              :  *
    1882              :  * Note: abbrev is matched case-sensitively; it should be all-upper-case.
    1883              :  */
    1884              : bool
    1885         4961 : pg_timezone_abbrev_is_known(const char *abbrev,
    1886              :                             bool *isfixed,
    1887              :                             long int *gmtoff,
    1888              :                             int *isdst,
    1889              :                             const pg_tz *tz)
    1890              : {
    1891         4961 :     bool        result = false;
    1892         4961 :     const struct state *sp = &tz->state;
    1893              :     const char *abbrs;
    1894              :     int         abbrind;
    1895              : 
    1896              :     /*
    1897              :      * Locate the abbreviation in the zone's abbreviation list.  We assume
    1898              :      * there are not duplicates in the list.
    1899              :      */
    1900         4961 :     abbrs = sp->chars;
    1901         4961 :     abbrind = 0;
    1902        28349 :     while (abbrind < sp->charcnt)
    1903              :     {
    1904        23541 :         if (strcmp(abbrev, abbrs + abbrind) == 0)
    1905          153 :             break;
    1906        93592 :         while (abbrs[abbrind] != '\0')
    1907        70204 :             abbrind++;
    1908        23388 :         abbrind++;
    1909              :     }
    1910         4961 :     if (abbrind >= sp->charcnt)
    1911         4808 :         return false;           /* definitely not there */
    1912              : 
    1913              :     /*
    1914              :      * Scan the ttinfo array to find uses of the abbreviation.
    1915              :      */
    1916         1211 :     for (int i = 0; i < sp->typecnt; i++)
    1917              :     {
    1918         1058 :         const struct ttinfo *ttisp = &sp->ttis[i];
    1919              : 
    1920         1058 :         if (ttisp->tt_desigidx == abbrind)
    1921              :         {
    1922          290 :             if (!result)
    1923              :             {
    1924              :                 /* First usage */
    1925          153 :                 *isfixed = true;    /* for the moment */
    1926          153 :                 *gmtoff = ttisp->tt_utoff;
    1927          153 :                 *isdst = ttisp->tt_isdst;
    1928          153 :                 result = true;
    1929              :             }
    1930              :             else
    1931              :             {
    1932              :                 /* Second or later usage, does it match? */
    1933          137 :                 if (*gmtoff != ttisp->tt_utoff ||
    1934          137 :                     *isdst != ttisp->tt_isdst)
    1935              :                 {
    1936            0 :                     *isfixed = false;
    1937            0 :                     break;      /* no point in looking further */
    1938              :                 }
    1939              :             }
    1940              :         }
    1941              :     }
    1942              : 
    1943          153 :     return result;
    1944              : }
    1945              : 
    1946              : /*
    1947              :  * Iteratively fetch all the abbreviations used in the given time zone.
    1948              :  *
    1949              :  * *indx is a state counter that the caller must initialize to zero
    1950              :  * before the first call, and not touch between calls.
    1951              :  *
    1952              :  * Returns the next known abbreviation, or NULL if there are no more.
    1953              :  *
    1954              :  * Note: the caller typically applies pg_interpret_timezone_abbrev()
    1955              :  * to each result.  While that nominally results in O(N^2) time spent
    1956              :  * searching the sp->chars[] array, we don't expect any zone to have
    1957              :  * enough abbreviations to make that meaningful.
    1958              :  */
    1959              : const char *
    1960          168 : pg_get_next_timezone_abbrev(int *indx,
    1961              :                             const pg_tz *tz)
    1962              : {
    1963              :     const char *result;
    1964          168 :     const struct state *sp = &tz->state;
    1965              :     const char *abbrs;
    1966              :     int         abbrind;
    1967              : 
    1968              :     /* If we're still in range, the result is the current abbrev. */
    1969          168 :     abbrs = sp->chars;
    1970          168 :     abbrind = *indx;
    1971          168 :     if (abbrind < 0 || abbrind >= sp->charcnt)
    1972           28 :         return NULL;
    1973          140 :     result = abbrs + abbrind;
    1974              : 
    1975              :     /* Advance *indx past this abbrev and its trailing null. */
    1976          560 :     while (abbrs[abbrind] != '\0')
    1977          420 :         abbrind++;
    1978          140 :     abbrind++;
    1979          140 :     *indx = abbrind;
    1980              : 
    1981          140 :     return result;
    1982              : }
    1983              : 
    1984              : /*
    1985              :  * If the given timezone uses only one GMT offset, store that offset
    1986              :  * into *gmtoff and return true, else return false.
    1987              :  */
    1988              : bool
    1989          621 : pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
    1990              : {
    1991              :     /*
    1992              :      * The zone could have more than one ttinfo, if it's historically used
    1993              :      * more than one abbreviation.  We return true as long as they all have
    1994              :      * the same gmtoff.
    1995              :      */
    1996              :     const struct state *sp;
    1997              :     int         i;
    1998              : 
    1999          621 :     sp = &tz->state;
    2000          639 :     for (i = 1; i < sp->typecnt; i++)
    2001              :     {
    2002           74 :         if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
    2003           56 :             return false;
    2004              :     }
    2005          565 :     *gmtoff = sp->ttis[0].tt_utoff;
    2006          565 :     return true;
    2007              : }
    2008              : 
    2009              : /*
    2010              :  * Return the name of the current timezone
    2011              :  */
    2012              : const char *
    2013        40303 : pg_get_timezone_name(pg_tz *tz)
    2014              : {
    2015        40303 :     if (tz)
    2016        40303 :         return tz->TZname;
    2017            0 :     return NULL;
    2018              : }
    2019              : 
    2020              : /*
    2021              :  * Check whether timezone is acceptable.
    2022              :  *
    2023              :  * What we are doing here is checking for leap-second-aware timekeeping.
    2024              :  * We need to reject such TZ settings because they'll wreak havoc with our
    2025              :  * date/time arithmetic.
    2026              :  */
    2027              : bool
    2028        23473 : pg_tz_acceptable(pg_tz *tz)
    2029              : {
    2030              :     struct pg_tm *tt;
    2031              :     pg_time_t   time2000;
    2032              : 
    2033              :     /*
    2034              :      * To detect leap-second timekeeping, run pg_localtime for what should be
    2035              :      * GMT midnight, 2000-01-01.  Insist that the tm_sec value be zero; any
    2036              :      * other result has to be due to leap seconds.
    2037              :      */
    2038        23473 :     time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
    2039        23473 :     tt = pg_localtime(&time2000, tz);
    2040        23473 :     if (!tt || tt->tm_sec != 0)
    2041            0 :         return false;
    2042              : 
    2043        23473 :     return true;
    2044              : }
        

Generated by: LCOV version 2.0-1