LCOV - differential code coverage report
Current view: top level - src/timezone - localtime.c (source / functions) Coverage Total Hit UNC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: 77aeca80249c9e640c811e80633a2e334a9320de vs 38afc3dcb25c45b744d4025029ce0a6c90b7059f Lines: 82.8 % 793 657 69 67 3 1 257 396 4 14 97 259
Current Date: 2026-07-25 19:08:27 +0900 Functions: 94.6 % 37 35 2 22 13 10
Baseline: lcov-20260725-baseline Branches: 67.4 % 546 368 106 72 3 148 217 5 9
Baseline Date: 2026-07-25 19:09:19 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 78.8 % 326 257 69 257
(30,360] days: 100.0 % 10 10 10
(360..) days: 85.3 % 457 390 67 3 1 386 4 14
Function coverage date bins:
(7,30] days: 85.7 % 14 12 2 12
(30,360] days: 100.0 % 3 3 2 1
(360..) days: 100.0 % 20 20 8 12
Branch coverage date bins:
(7,30] days: 58.3 % 254 148 106 148
(30,360] days: 100.0 % 2 2 2
(360..) days: 71.7 % 304 218 72 3 215 5 9

 Age         Owner                    Branch data    TLA  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
   24 tgl@sss.pgh.pa.us          73                 :GNC     6328222 : leapcount(ATTRIBUTE_MAYBE_UNUSED struct state const *sp)
                                 74                 :                : {
                                 75                 :                : #if TZ_RUNTIME_LEAPS
                                 76                 :        6328222 :     return sp->leapcnt;
                                 77                 :                : #else
                                 78                 :                :     return 0;
                                 79                 :                : #endif
                                 80                 :                : }
                                 81                 :                : static void
                                 82                 :          37621 : set_leapcount(ATTRIBUTE_MAYBE_UNUSED struct state *sp,
                                 83                 :                :               ATTRIBUTE_MAYBE_UNUSED int leapcnt)
                                 84                 :                : {
                                 85                 :                : #if TZ_RUNTIME_LEAPS
                                 86                 :          37621 :     sp->leapcnt = leapcnt;
                                 87                 :                : #endif
                                 88                 :          37621 : }
                                 89                 :                : static struct lsinfo
   24 tgl@sss.pgh.pa.us          90                 :UNC           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
   24 tgl@sss.pgh.pa.us         152                 :GNC       20243 : init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst,
                                153                 :                :             desigidx_type desigidx)
                                154                 :                : {
 2565 tgl@sss.pgh.pa.us         155                 :CBC       20243 :     s->tt_utoff = utoff;
 3771                           156                 :          20243 :     s->tt_isdst = isdst;
 2565                           157                 :          20243 :     s->tt_desigidx = desigidx;
 3771                           158                 :          20243 :     s->tt_ttisstd = false;
 2565                           159                 :          20243 :     s->tt_ttisut = false;
 3771                           160                 :          20243 : }
                                161                 :                : 
                                162                 :                : static int_fast32_2s
 2836                           163                 :         195362 : detzcode(const char *const codep)
                                164                 :                : {
                                165                 :                :     int         i;
                                166                 :                :     int_fast32_2s
   24 tgl@sss.pgh.pa.us         167                 :GNC      195362 :                 maxval = TWO_31_MINUS_1,
                                168                 :         195362 :                 minval = -1 - maxval,
                                169                 :                :                 result;
                                170                 :                : 
 3771 tgl@sss.pgh.pa.us         171                 :CBC      195362 :     result = codep[0] & 0x7f;
                                172         [ +  + ]:         781448 :     for (i = 1; i < 4; ++i)
 8121 bruce@momjian.us          173                 :         586086 :         result = (result << 8) | (codep[i] & 0xff);
                                174                 :                : 
 3771 tgl@sss.pgh.pa.us         175         [ +  + ]:         195362 :     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                 :          35234 :         result += minval;
                                182                 :                :     }
 8121 bruce@momjian.us          183                 :         195362 :     return result;
                                184                 :                : }
                                185                 :                : 
                                186                 :                : static int_fast64_t
 2836 tgl@sss.pgh.pa.us         187                 :         864496 : detzcode64(const char *const codep)
                                188                 :                : {
                                189                 :                :     int_fast64_t result;
                                190                 :                :     int         i;
  246 peter@eisentraut.org      191                 :         864496 :     int_fast64_t one = 1;
                                192                 :         864496 :     int_fast64_t halfmaxval = one << (64 - 2);
                                193                 :         864496 :     int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
                                194                 :         864496 :     int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
                                195                 :                : 
 3771 tgl@sss.pgh.pa.us         196                 :         864496 :     result = codep[0] & 0x7f;
                                197         [ +  + ]:        6915968 :     for (i = 1; i < 8; ++i)
                                198                 :        6051472 :         result = (result << 8) | (codep[i] & 0xff);
                                199                 :                : 
                                200         [ +  + ]:         864496 :     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                 :                :          */
  246 peter@eisentraut.org      206                 :         331539 :         result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
 3771 tgl@sss.pgh.pa.us         207                 :         331539 :         result += minval;
                                208                 :                :     }
 6734                           209                 :         864496 :     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
   24 tgl@sss.pgh.pa.us         261                 :GNC       12374 : 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                 :          12374 :     union local_storage *lsp = *lspp;
                                270                 :                :     union input_buffer *up;
 3771 tgl@sss.pgh.pa.us         271                 :CBC       12374 :     int         tzheadsize = sizeof(struct tzhead);
                                272                 :                : 
                                273                 :          12374 :     sp->goback = sp->goahead = false;
                                274                 :                : 
                                275         [ -  + ]:          12374 :     if (!name)
                                276                 :                :     {
 3771 tgl@sss.pgh.pa.us         277                 :UBC           0 :         name = TZDEFAULT;
                                278         [ #  # ]:              0 :         if (!name)
                                279                 :              0 :             return EINVAL;
                                280                 :                :     }
                                281                 :                : 
 7222 tgl@sss.pgh.pa.us         282         [ -  + ]:CBC       12374 :     if (name[0] == ':')
 7222 tgl@sss.pgh.pa.us         283                 :UBC           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                 :                :      */
 7222 tgl@sss.pgh.pa.us         291                 :CBC       12374 :     fid = pg_open_tzfile(name, canonname);
                                292         [ +  + ]:          12374 :     if (fid < 0)
 3771                           293                 :            403 :         return ENOENT;          /* pg_open_tzfile may not set errno */
                                294                 :                : 
   24 tgl@sss.pgh.pa.us         295                 :GNC       11971 :     up = &lsp->u.u;
 3771 tgl@sss.pgh.pa.us         296                 :CBC       11971 :     nread = read(fid, up->buf, sizeof up->buf);
                                297         [ -  + ]:          11971 :     if (nread < tzheadsize)
                                298                 :                :     {
 3771 tgl@sss.pgh.pa.us         299         [ #  # ]:UBC           0 :         int         err = nread < 0 ? errno : EINVAL;
                                300                 :                : 
                                301                 :              0 :         close(fid);
                                302                 :              0 :         return err;
                                303                 :                :     }
 3771 tgl@sss.pgh.pa.us         304         [ -  + ]:CBC       11971 :     if (close(fid) < 0)
 3771 tgl@sss.pgh.pa.us         305                 :UBC           0 :         return errno;
                                306                 :                : 
 6734 tgl@sss.pgh.pa.us         307         [ +  + ]:CBC       35913 :     for (stored = 4; stored <= 8; stored *= 2)
                                308                 :                :     {
   24 tgl@sss.pgh.pa.us         309                 :GNC       23942 :         char        version = up->tzhead.tzh_version[0];
                                310   [ +  +  +  - ]:          23942 :         bool        skip_datablock = stored == 4 && version;
                                311                 :                :         int_fast32_t datablock_size;
                                312                 :                :         int_fast32_2s
                                313                 :          23942 :                     ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt),
                                314                 :          23942 :                     ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt),
                                315                 :          23942 :                     leapcnt = detzcode(up->tzhead.tzh_leapcnt),
                                316                 :          23942 :                     timecnt = detzcode(up->tzhead.tzh_timecnt),
                                317                 :          23942 :                     typecnt = detzcode(up->tzhead.tzh_typecnt),
                                318                 :          23942 :                     charcnt = detzcode(up->tzhead.tzh_charcnt);
 3771 tgl@sss.pgh.pa.us         319                 :CBC       23942 :         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                 :                :          */
   24 tgl@sss.pgh.pa.us         326   [ +  -  -  + ]:GNC       47884 :         if (!(0 <= leapcnt
                                327         [ +  - ]:          23942 :               && leapcnt <= (TZ_RUNTIME_LEAPS ? TZ_MAX_LEAPS : 0)
                                328   [ +  -  +  - ]:          23942 :               && 0 <= typecnt && typecnt <= TZ_MAX_TYPES
                                329   [ +  -  +  - ]:          23942 :               && 0 <= timecnt && timecnt <= TZ_MAX_TIMES
                                330   [ +  -  +  - ]:          23942 :               && 0 <= charcnt && charcnt <= TZ_MAX_CHARS
                                331   [ +  -  +  - ]:          23942 :               && 0 <= ttisstdcnt && ttisstdcnt <= TZ_MAX_TYPES
                                332         [ +  - ]:          23942 :               && 0 <= ttisutcnt && ttisutcnt <= TZ_MAX_TYPES))
 3771 tgl@sss.pgh.pa.us         333                 :UBC           0 :             return EINVAL;
                                334                 :                :         datablock_size
   24 tgl@sss.pgh.pa.us         335                 :GNC       23942 :             = (timecnt * stored /* ats */
 3771 tgl@sss.pgh.pa.us         336                 :CBC       23942 :                + timecnt        /* types */
                                337                 :          23942 :                + typecnt * 6    /* ttinfos */
                                338                 :          23942 :                + charcnt        /* chars */
                                339                 :          23942 :                + leapcnt * (stored + 4) /* lsinfos */
                                340                 :          23942 :                + ttisstdcnt     /* ttisstds */
                                341                 :                :                + ttisutcnt);    /* ttisuts */
   24 tgl@sss.pgh.pa.us         342         [ -  + ]:GNC       23942 :         if (nread < tzheadsize + datablock_size)
 3771 tgl@sss.pgh.pa.us         343                 :UBC           0 :             return EINVAL;
   24 tgl@sss.pgh.pa.us         344         [ +  + ]:GNC       23942 :         if (skip_datablock)
                                345                 :          11971 :             p += datablock_size;
                                346   [ +  -  +  -  :          11971 :         else if (!((ttisstdcnt == typecnt || ttisstdcnt == 0)
                                              +  - ]
                                347         [ -  + ]:          11971 :                    && (ttisutcnt == typecnt || ttisutcnt == 0)))
   24 tgl@sss.pgh.pa.us         348                 :UNC           0 :             return EINVAL;
                                349                 :                :         else
                                350                 :                :         {
   24 tgl@sss.pgh.pa.us         351                 :GNC       11971 :             int_fast64_t prevtr = -1;
                                352                 :          11971 :             int_fast32_2s prevcorr = -1;
                                353                 :                : 
                                354                 :          11971 :             set_leapcount(sp, leapcnt);
                                355                 :          11971 :             sp->timecnt = timecnt;
                                356                 :          11971 :             sp->typecnt = typecnt;
                                357                 :          11971 :             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                 :          11971 :             timecnt = 0;
                                365         [ +  + ]:         876467 :             for (i = 0; i < sp->timecnt; ++i)
                                366                 :                :             {
                                367                 :         864496 :                 int_fast64_t at
                                368         [ -  + ]:         864496 :                 = stored == 4 ? detzcode(p) : detzcode64(p);
                                369                 :                : 
                                370                 :         864496 :                 sp->types[i] = at <= TIME_T_MAX;
                                371         [ +  - ]:         864496 :                 if (sp->types[i])
                                372                 :                :                 {
                                373                 :         864496 :                     pg_time_t   attime
                                374                 :                :                     = ((TYPE_SIGNED(pg_time_t) ? at < TIME_T_MIN : at < 0)
                                375                 :                :                        ? TIME_T_MIN : at);
                                376                 :                : 
                                377   [ +  +  -  + ]:         864496 :                     if (timecnt && attime <= sp->ats[timecnt - 1])
                                378                 :                :                     {
   24 tgl@sss.pgh.pa.us         379         [ #  # ]:UNC           0 :                         if (attime < sp->ats[timecnt - 1])
                                380                 :              0 :                             return EINVAL;
                                381                 :              0 :                         sp->types[i - 1] = 0;
                                382                 :              0 :                         timecnt--;
                                383                 :                :                     }
   24 tgl@sss.pgh.pa.us         384                 :GNC      864496 :                     sp->ats[timecnt++] = attime;
                                385                 :                :                 }
                                386                 :         864496 :                 p += stored;
                                387                 :                :             }
                                388                 :                : 
                                389                 :          11971 :             timecnt = 0;
                                390         [ +  + ]:         876467 :             for (i = 0; i < sp->timecnt; ++i)
                                391                 :                :             {
                                392                 :         864496 :                 unsigned char typ = *p++;
                                393                 :                : 
                                394         [ -  + ]:         864496 :                 if (sp->typecnt <= typ)
   24 tgl@sss.pgh.pa.us         395                 :UNC           0 :                     return EINVAL;
   24 tgl@sss.pgh.pa.us         396         [ +  - ]:GNC      864496 :                 if (sp->types[i])
                                397                 :         864496 :                     sp->types[timecnt++] = typ;
                                398                 :                :             }
                                399                 :          11971 :             sp->timecnt = timecnt;
                                400         [ +  + ]:          63681 :             for (i = 0; i < sp->typecnt; ++i)
                                401                 :                :             {
                                402                 :                :                 struct ttinfo *ttisp;
                                403                 :                :                 unsigned char isdst,
                                404                 :                :                             desigidx;
                                405                 :          51710 :                 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         [ -  + ]:          51710 :                 if (utoff < -TWO_31_MINUS_1)
 3228 tgl@sss.pgh.pa.us         413                 :UBC           0 :                     return EINVAL;
                                414                 :                : 
   24 tgl@sss.pgh.pa.us         415                 :GNC       51710 :                 ttisp = &sp->ttis[i];
                                416                 :          51710 :                 ttisp->tt_utoff = utoff;
                                417                 :          51710 :                 p += 4;
                                418                 :          51710 :                 isdst = *p++;
                                419         [ -  + ]:          51710 :                 if (!(isdst < 2))
   24 tgl@sss.pgh.pa.us         420                 :UNC           0 :                     return EINVAL;
   24 tgl@sss.pgh.pa.us         421                 :GNC       51710 :                 ttisp->tt_isdst = isdst;
                                422                 :          51710 :                 desigidx = *p++;
                                423         [ -  + ]:          51710 :                 if (!(desigidx < sp->charcnt))
   24 tgl@sss.pgh.pa.us         424                 :UNC           0 :                     return EINVAL;
   24 tgl@sss.pgh.pa.us         425                 :GNC       51710 :                 ttisp->tt_desigidx = desigidx;
                                426                 :                :             }
                                427         [ +  + ]:         215048 :             for (i = 0; i < sp->charcnt; ++i)
                                428                 :         203077 :                 sp->chars[i] = *p++;
                                429                 :                : 
                                430                 :                :             /*
                                431                 :                :              * Ensure '\0'-terminated, and make it safe to call ttunspecified
                                432                 :                :              * later.
                                433                 :                :              */
                                434                 :          11971 :             memset(&sp->chars[i], 0, CHARS_EXTRA);
                                435                 :                : 
                                436                 :                :             /* Read leap seconds, discarding those out of pg_time_t range.  */
                                437                 :          11971 :             leapcnt = 0;
                                438         [ -  + ]:          11971 :             for (i = 0; i < leapcount(sp); i++)
                                439                 :                :             {
   24 tgl@sss.pgh.pa.us         440         [ #  # ]:UNC           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))))
 3771 tgl@sss.pgh.pa.us         464                 :UBC           0 :                     return EINVAL;
   24 tgl@sss.pgh.pa.us         465                 :UNC           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                 :                :             }
   24 tgl@sss.pgh.pa.us         478                 :GNC       11971 :             set_leapcount(sp, leapcnt);
                                479                 :                : 
                                480         [ +  + ]:          63681 :             for (i = 0; i < sp->typecnt; ++i)
                                481                 :                :             {
                                482                 :                :                 struct ttinfo *ttisp;
                                483                 :                : 
                                484                 :          51710 :                 ttisp = &sp->ttis[i];
                                485         [ +  - ]:          51710 :                 if (ttisstdcnt == 0)
                                486                 :          51710 :                     ttisp->tt_ttisstd = false;
                                487                 :                :                 else
                                488                 :                :                 {
   24 tgl@sss.pgh.pa.us         489   [ #  #  #  # ]:UNC           0 :                     if (*p != true && *p != false)
                                490                 :              0 :                         return EINVAL;
                                491                 :              0 :                     ttisp->tt_ttisstd = *p++;
                                492                 :                :                 }
                                493                 :                :             }
   24 tgl@sss.pgh.pa.us         494         [ +  + ]:GNC       63681 :             for (i = 0; i < sp->typecnt; ++i)
                                495                 :                :             {
                                496                 :                :                 struct ttinfo *ttisp;
                                497                 :                : 
                                498                 :          51710 :                 ttisp = &sp->ttis[i];
                                499         [ +  - ]:          51710 :                 if (ttisutcnt == 0)
                                500                 :          51710 :                     ttisp->tt_ttisut = false;
                                501                 :                :                 else
                                502                 :                :                 {
   24 tgl@sss.pgh.pa.us         503   [ #  #  #  # ]:UNC           0 :                     if (*p != true && *p != false)
                                504                 :              0 :                         return EINVAL;
                                505                 :              0 :                     ttisp->tt_ttisut = *p++;
                                506                 :                :                 }
                                507                 :                :             }
                                508                 :                :         }
                                509                 :                : 
 3771 tgl@sss.pgh.pa.us         510                 :CBC       23942 :         nread -= p - up->buf;
                                511                 :          23942 :         memmove(up->buf, p, nread);
                                512                 :                : 
                                513                 :                :         /* If this is an old file, we're done.  */
   24 tgl@sss.pgh.pa.us         514         [ -  + ]:GNC       23942 :         if (!version)
   24 tgl@sss.pgh.pa.us         515                 :UNC           0 :             break;
                                516                 :                :     }
   24 tgl@sss.pgh.pa.us         517   [ +  -  +  - ]:GNC       11971 :     if ((tzloadflags & TZLOAD_TZSTRING) && nread > 2 &&
 3771 tgl@sss.pgh.pa.us         518   [ +  -  +  - ]:CBC       11971 :         up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
 6734                           519         [ +  - ]:          11971 :         sp->typecnt + 2 <= TZ_MAX_TYPES)
                                520                 :                :     {
 3771                           521                 :          11971 :         struct state *ts = &lsp->u.st;
                                522                 :                : 
                                523                 :          11971 :         up->buf[nread - 1] = '\0';
   24 tgl@sss.pgh.pa.us         524         [ +  - ]:GNC       11971 :         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                 :                :              */
 3771 tgl@sss.pgh.pa.us         534                 :CBC       11971 :             int         gotabbr = 0;
                                535                 :          11971 :             int         charcnt = sp->charcnt;
                                536                 :                : 
 2836                           537         [ +  + ]:          30493 :             for (i = 0; i < ts->typecnt; i++)
                                538                 :                :             {
 2565                           539                 :          18522 :                 char       *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
                                540                 :                :                 int         j;
                                541                 :                : 
 3771                           542         [ +  + ]:         155393 :                 for (j = 0; j < charcnt; j++)
                                543         [ +  + ]:         155333 :                     if (strcmp(sp->chars + j, tsabbr) == 0)
                                544                 :                :                     {
 2565                           545                 :          18462 :                         ts->ttis[i].tt_desigidx = j;
 3771                           546                 :          18462 :                         gotabbr++;
                                547                 :          18462 :                         break;
                                548                 :                :                     }
                                549         [ +  + ]:          18522 :                 if (!(j < charcnt))
                                550                 :                :                 {
   24 tgl@sss.pgh.pa.us         551                 :GNC          60 :                     int         tsabbrlen = strnlen(tsabbr, TZ_MAX_CHARS - j);
                                552                 :                : 
 3771 tgl@sss.pgh.pa.us         553         [ +  - ]:CBC          60 :                     if (j + tsabbrlen < TZ_MAX_CHARS)
                                554                 :                :                     {
   24 tgl@sss.pgh.pa.us         555                 :GNC          60 :                         char       *cp = sp->chars + j;
                                556                 :                : 
                                557                 :             60 :                         memcpy(cp, tsabbr, tsabbrlen);
                                558                 :             60 :                         cp += tsabbrlen;
                                559                 :             60 :                         *cp = '\0';
 3771 tgl@sss.pgh.pa.us         560                 :CBC          60 :                         charcnt = j + tsabbrlen + 1;
 2565                           561                 :             60 :                         ts->ttis[i].tt_desigidx = j;
 3771                           562                 :             60 :                         gotabbr++;
                                563                 :                :                     }
                                564                 :                :                 }
                                565                 :                :             }
 2836                           566         [ +  - ]:          11971 :             if (gotabbr == ts->typecnt)
                                567                 :                :             {
 3771                           568                 :          11971 :                 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                 :                :                  */
 3373                           575                 :          11971 :                 while (1 < sp->timecnt
                                576         [ +  + ]:          12319 :                        && (sp->types[sp->timecnt - 1]
                                577         [ +  + ]:          10160 :                            == sp->types[sp->timecnt - 2]))
                                578                 :            348 :                     sp->timecnt--;
                                579                 :                : 
   24 tgl@sss.pgh.pa.us         580                 :GNC       11971 :                 sp->goahead = ts->goahead;
                                581                 :                : 
 3771 tgl@sss.pgh.pa.us         582         [ +  + ]:CBC     5278329 :                 for (i = 0; i < ts->timecnt; i++)
                                583                 :                :                 {
   24 tgl@sss.pgh.pa.us         584                 :GNC     5266358 :                     pg_time_t   t = ts->ats[i];
                                585                 :                : 
                                586         [ +  - ]:        5266358 :                     if (increment_overflow_time(&t, leapcorr(sp, t))
                                587         [ +  - ]:        5266358 :                         || (0 < sp->timecnt
                                588         [ +  + ]:        5266358 :                             && t <= sp->ats[sp->timecnt - 1]))
                                589                 :           6133 :                         continue;
                                590         [ -  + ]:        5260225 :                     if (TZ_MAX_TIMES <= sp->timecnt)
                                591                 :                :                     {
   24 tgl@sss.pgh.pa.us         592                 :UNC           0 :                         sp->goahead = false;
                                593                 :              0 :                         break;
                                594                 :                :                     }
   24 tgl@sss.pgh.pa.us         595                 :GNC     5260225 :                     sp->ats[sp->timecnt] = t;
 3771 tgl@sss.pgh.pa.us         596                 :CBC     5260225 :                     sp->types[sp->timecnt] = (sp->typecnt
                                597                 :        5260225 :                                               + ts->types[i]);
                                598                 :        5260225 :                     sp->timecnt++;
                                599                 :                :                 }
 2836                           600         [ +  + ]:          30493 :                 for (i = 0; i < ts->typecnt; i++)
                                601                 :          18522 :                     sp->ttis[sp->typecnt++] = ts->ttis[i];
                                602                 :                :             }
                                603                 :                :         }
                                604                 :                :     }
                                605         [ -  + ]:          11971 :     if (sp->typecnt == 0)
 2836 tgl@sss.pgh.pa.us         606                 :UBC           0 :         return EINVAL;
                                607                 :                : 
 8121 bruce@momjian.us          608                 :CBC       11971 :     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
   24 tgl@sss.pgh.pa.us         618                 :GNC       12374 : 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                 :          12374 :     lsp = &ls;
                                625                 :          12374 :     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                 :         192648 : is_digit(char c)
                                640                 :                : {
                                641   [ +  +  +  + ]:         192648 :     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 *
 7705 neilc@samurai.com         651                 :CBC       17754 : getzname(const char *strp)
                                652                 :                : {
                                653                 :                :     char        c;
                                654                 :                : 
 8121 bruce@momjian.us          655   [ +  +  +  +  :          74647 :     while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
                                     +  +  +  +  +  
                                                 + ]
                                656                 :                :            c != '+')
 8100                           657                 :          56893 :         ++strp;
 8121                           658                 :          17754 :     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 *
 2836 tgl@sss.pgh.pa.us         672                 :           2671 : getqzname(const char *strp, const int delim)
                                673                 :                : {
                                674                 :                :     int         c;
                                675                 :                : 
 6734                           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 *
 2836                           689                 :          55185 : getnum(const char *strp, int *const nump, const int min, const int max)
                                690                 :                : {
                                691                 :                :     char        c;
                                692                 :                :     int         num;
                                693                 :                : 
 8121 bruce@momjian.us          694   [ +  -  +  + ]:          55185 :     if (strp == NULL || !is_digit(c = *strp))
 8121 bruce@momjian.us          695                 :GBC         182 :         return NULL;
 8121 bruce@momjian.us          696                 :CBC       55003 :     num = 0;
                                697                 :                :     do
                                698                 :                :     {
                                699                 :          63002 :         num = num * 10 + (c - '0');
                                700         [ -  + ]:          63002 :         if (num > max)
 8100 bruce@momjian.us          701                 :UBC           0 :             return NULL;        /* illegal value */
 8121 bruce@momjian.us          702                 :CBC       63002 :         c = *++strp;
                                703         [ +  + ]:          63002 :     } while (is_digit(c));
                                704         [ -  + ]:          55003 :     if (num < min)
 8100 bruce@momjian.us          705                 :UBC           0 :         return NULL;            /* illegal value */
 8121 bruce@momjian.us          706                 :CBC       55003 :     *nump = num;
                                707                 :          55003 :     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 *
  246 peter@eisentraut.org      719                 :          15435 : getsecs(const char *strp, int_fast32_t *const secsp)
                                720                 :                : {
                                721                 :                :     int         num;
   24 tgl@sss.pgh.pa.us         722                 :GNC       15435 :     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                 :                :      */
 8121 bruce@momjian.us          729                 :CBC       15435 :     strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
                                730         [ +  + ]:          15435 :     if (strp == NULL)
 8121 bruce@momjian.us          731                 :GBC         182 :         return NULL;
   24 tgl@sss.pgh.pa.us         732                 :GNC       15253 :     *secsp = num * secsperhour;
 8100 bruce@momjian.us          733         [ +  + ]:CBC       15253 :     if (*strp == ':')
                                734                 :                :     {
 8121                           735                 :            366 :         ++strp;
                                736                 :            366 :         strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
                                737         [ -  + ]:            366 :         if (strp == NULL)
 8121 bruce@momjian.us          738                 :UBC           0 :             return NULL;
 8121 bruce@momjian.us          739                 :CBC         366 :         *secsp += num * SECSPERMIN;
 8100                           740         [ -  + ]:            366 :         if (*strp == ':')
                                741                 :                :         {
 8121 bruce@momjian.us          742                 :UBC           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                 :                :     }
 8121 bruce@momjian.us          750                 :CBC       15253 :     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 *
  246 peter@eisentraut.org      761                 :          15435 : getoffset(const char *strp, int_fast32_t *const offsetp)
                                762                 :                : {
 3771 tgl@sss.pgh.pa.us         763                 :          15435 :     bool        neg = false;
                                764                 :                : 
 8100 bruce@momjian.us          765         [ +  + ]:          15435 :     if (*strp == '-')
                                766                 :                :     {
 3771 tgl@sss.pgh.pa.us         767                 :           3387 :         neg = true;
 8121 bruce@momjian.us          768                 :           3387 :         ++strp;
                                769                 :                :     }
 8100                           770         [ +  + ]:          12048 :     else if (*strp == '+')
 8121                           771                 :             85 :         ++strp;
                                772                 :          15435 :     strp = getsecs(strp, offsetp);
                                773         [ +  + ]:          15435 :     if (strp == NULL)
 8100 bruce@momjian.us          774                 :GBC         182 :         return NULL;            /* illegal time */
 8121 bruce@momjian.us          775         [ +  + ]:CBC       15253 :     if (neg)
                                776                 :           3387 :         *offsetp = -*offsetp;
                                777                 :          15253 :     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 *
 2836 tgl@sss.pgh.pa.us         789                 :          13128 : getrule(const char *strp, struct rule *const rulep)
                                790                 :                : {
 8100 bruce@momjian.us          791         [ -  + ]:          13128 :     if (*strp == 'J')
                                792                 :                :     {
                                793                 :                :         /*
                                794                 :                :          * Julian day.
                                795                 :                :          */
 8121 bruce@momjian.us          796                 :UBC           0 :         rulep->r_type = JULIAN_DAY;
                                797                 :              0 :         ++strp;
                                798                 :              0 :         strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
                                799                 :                :     }
 8100 bruce@momjian.us          800         [ +  - ]:CBC       13128 :     else if (*strp == 'M')
                                801                 :                :     {
                                802                 :                :         /*
                                803                 :                :          * Month, week, day.
                                804                 :                :          */
 8121                           805                 :          13128 :         rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
                                806                 :          13128 :         ++strp;
                                807                 :          13128 :         strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
                                808         [ -  + ]:          13128 :         if (strp == NULL)
 8121 bruce@momjian.us          809                 :UBC           0 :             return NULL;
 8121 bruce@momjian.us          810         [ -  + ]:CBC       13128 :         if (*strp++ != '.')
 8121 bruce@momjian.us          811                 :UBC           0 :             return NULL;
 8121 bruce@momjian.us          812                 :CBC       13128 :         strp = getnum(strp, &rulep->r_week, 1, 5);
                                813         [ -  + ]:          13128 :         if (strp == NULL)
 8121 bruce@momjian.us          814                 :UBC           0 :             return NULL;
 8121 bruce@momjian.us          815         [ -  + ]:CBC       13128 :         if (*strp++ != '.')
 8121 bruce@momjian.us          816                 :UBC           0 :             return NULL;
 8121 bruce@momjian.us          817                 :CBC       13128 :         strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
                                818                 :                :     }
 8100 bruce@momjian.us          819         [ #  # ]:UBC           0 :     else if (is_digit(*strp))
                                820                 :                :     {
                                821                 :                :         /*
                                822                 :                :          * Day of year.
                                823                 :                :          */
 8121                           824                 :              0 :         rulep->r_type = DAY_OF_YEAR;
                                825                 :              0 :         strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
                                826                 :                :     }
                                827                 :                :     else
 8100                           828                 :              0 :         return NULL;            /* invalid format */
 8121 bruce@momjian.us          829         [ -  + ]:CBC       13128 :     if (strp == NULL)
 8121 bruce@momjian.us          830                 :UBC           0 :         return NULL;
 8100 bruce@momjian.us          831         [ +  + ]:CBC       13128 :     if (*strp == '/')
                                832                 :                :     {
                                833                 :                :         /*
                                834                 :                :          * Time specified.
                                835                 :                :          */
 8121                           836                 :           1520 :         ++strp;
 3771 tgl@sss.pgh.pa.us         837                 :           1520 :         strp = getoffset(strp, &rulep->r_time);
                                838                 :                :     }
                                839                 :                :     else
 3321                           840                 :          11608 :         rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
 8121 bruce@momjian.us          841                 :          13128 :     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
 2836 tgl@sss.pgh.pa.us         850                 :        5277456 : 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                 :                : 
 8121 bruce@momjian.us          863   [ +  +  +  +  :        5277456 :     leapyear = isleap(year);
                                              +  + ]
 8100                           864   [ -  -  +  - ]:        5277456 :     switch (rulep->r_type)
                                865                 :                :     {
                                866                 :                : 
 8100 bruce@momjian.us          867                 :UBC           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                 :                :              */
 3771 tgl@sss.pgh.pa.us         875                 :              0 :             value = (rulep->r_day - 1) * SECSPERDAY;
 8100 bruce@momjian.us          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                 :                :              */
 3771 tgl@sss.pgh.pa.us         886                 :              0 :             value = rulep->r_day * SECSPERDAY;
 8100 bruce@momjian.us          887                 :              0 :             break;
                                888                 :                : 
 8100 bruce@momjian.us          889                 :CBC     5277456 :         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                 :        5277456 :             m1 = (rulep->r_mon + 9) % 12 + 1;
                                900         [ -  + ]:        5277456 :             yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
                                901                 :        5277456 :             yy1 = yy0 / 100;
                                902                 :        5277456 :             yy2 = yy0 % 100;
                                903                 :        5277456 :             dow = ((26 * m1 - 2) / 10 +
                                904                 :        5277456 :                    1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
                                905         [ +  + ]:        5277456 :             if (dow < 0)
                                906                 :         950971 :                 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                 :        5277456 :             d = rulep->r_day - dow;
                                913         [ +  + ]:        5277456 :             if (d < 0)
                                914                 :        4458481 :                 d += DAYSPERWEEK;
                                915         [ +  + ]:        9908352 :             for (i = 1; i < rulep->r_week; ++i)
                                916                 :                :             {
                                917                 :        5032236 :                 if (d + DAYSPERWEEK >=
  247 peter@eisentraut.org      918         [ +  + ]:        5032236 :                     mon_lengths[leapyear][rulep->r_mon - 1])
 8121 bruce@momjian.us          919                 :         401340 :                     break;
 8100                           920                 :        4630896 :                 d += DAYSPERWEEK;
                                921                 :                :             }
                                922                 :                : 
                                923                 :                :             /*
                                924                 :                :              * "d" is the day-of-month (zero-origin) of the day we want.
                                925                 :                :              */
 3771 tgl@sss.pgh.pa.us         926                 :        5277456 :             value = d * SECSPERDAY;
                                927         [ +  + ]:       36559086 :             for (i = 0; i < rulep->r_mon - 1; ++i)
  247 peter@eisentraut.org      928                 :       31281630 :                 value += mon_lengths[leapyear][i] * SECSPERDAY;
 8100 bruce@momjian.us          929                 :        5277456 :             break;
                                930                 :                : 
   24 tgl@sss.pgh.pa.us         931                 :UNC           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                 :                :      */
 8121 bruce@momjian.us          940                 :CBC     5277456 :     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
   24 tgl@sss.pgh.pa.us         949                 :GNC       13861 : tzparse(const char *name, struct state *sp, struct state const *basep)
                                950                 :                : {
                                951                 :                :     const char *stdname;
 8100 bruce@momjian.us          952                 :CBC       13861 :     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;
   24 tgl@sss.pgh.pa.us         959                 :GNC       13861 :     pg_time_t   atlo = TIME_T_MIN,
                                960                 :          13861 :                 leaplo = TIME_T_MIN;
                                961                 :                : 
 8121 bruce@momjian.us          962                 :CBC       13861 :     stdname = name;
   24 tgl@sss.pgh.pa.us         963         [ +  + ]:GNC       13861 :     if (*name == '<')
                                964                 :                :     {
                                965                 :           2509 :         name++;
                                966                 :           2509 :         stdname = name;
                                967                 :           2509 :         name = getqzname(name, '>');
                                968         [ -  + ]:           2509 :         if (*name != '>')
   24 tgl@sss.pgh.pa.us         969                 :UNC           0 :             return false;
   24 tgl@sss.pgh.pa.us         970                 :GNC        2509 :         stdlen = name - stdname;
                                971                 :           2509 :         name++;
                                972                 :                :     }
                                973                 :                :     else
                                974                 :                :     {
                                975                 :          11352 :         name = getzname(name);
                                976                 :          11352 :         stdlen = name - stdname;
                                977                 :                :     }
                                978         [ -  + ]:          13861 :     if (stdlen > TZNAME_MAXIMUM) /* allow empty STD abbrev, unlike IANA */
 2838 tgl@sss.pgh.pa.us         979                 :UBC           0 :         return false;
   24 tgl@sss.pgh.pa.us         980                 :GNC       13861 :     name = getoffset(name, &stdoffset);
                                981         [ +  + ]:          13861 :     if (name == NULL)
                                982                 :            182 :         return false;
                                983                 :          13679 :     charcnt = stdlen + 1;
                                984         [ +  + ]:          13679 :     if (basep)
                                985                 :                :     {
                                986         [ +  + ]:          11971 :         if (0 < basep->timecnt)
                                987                 :          10272 :             atlo = basep->ats[basep->timecnt - 1];
                                988                 :          11971 :         set_leapcount(sp, leapcount(basep));
                                989         [ -  + ]:          11971 :         if (0 < leapcount(sp))
                                990                 :                :         {
                                991                 :                :             int         i;
                                992                 :                : 
   24 tgl@sss.pgh.pa.us         993         [ #  # ]:UNC           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
   24 tgl@sss.pgh.pa.us         999                 :GNC        1708 :         set_leapcount(sp, 0);   /* So, we're off a little.  */
                               1000                 :          13679 :     sp->goback = sp->goahead = false;
 8100 bruce@momjian.us         1001         [ +  + ]:CBC       13679 :     if (*name != '\0')
                               1002                 :                :     {
                               1003                 :                :         struct rule start,
                               1004                 :                :                     end;
                               1005                 :                :         int         year,
                               1006                 :                :                     yearbeg,
                               1007                 :                :                     yearlim,
                               1008                 :                :                     timecnt;
                               1009                 :                :         pg_time_t   janfirst;
   24 tgl@sss.pgh.pa.us        1010                 :GNC        6564 :         int_fast32_t janoffset = 0;
                               1011                 :                : 
 6734 tgl@sss.pgh.pa.us        1012         [ +  + ]:CBC        6564 :         if (*name == '<')
                               1013                 :                :         {
                               1014                 :            162 :             dstname = ++name;
                               1015                 :            162 :             name = getqzname(name, '>');
                               1016         [ -  + ]:            162 :             if (*name != '>')
 3771 tgl@sss.pgh.pa.us        1017                 :UBC           0 :                 return false;
 6734 tgl@sss.pgh.pa.us        1018                 :CBC         162 :             dstlen = name - dstname;
                               1019                 :            162 :             name++;
                               1020                 :                :         }
                               1021                 :                :         else
                               1022                 :                :         {
                               1023                 :           6402 :             dstname = name;
                               1024                 :           6402 :             name = getzname(name);
 2836                          1025                 :           6402 :             dstlen = name - dstname;    /* length of DST abbr. */
                               1026                 :                :         }
   24 tgl@sss.pgh.pa.us        1027   [ +  -  -  + ]:GNC        6564 :         if (!(0 < dstlen && dstlen <= TZNAME_MAXIMUM))
 3771 tgl@sss.pgh.pa.us        1028                 :UBC           0 :             return false;
 3771 tgl@sss.pgh.pa.us        1029                 :CBC        6564 :         charcnt += dstlen + 1;
 8100 bruce@momjian.us         1030   [ +  +  +  +  :           6564 :         if (*name != '\0' && *name != ',' && *name != ';')
                                              +  - ]
                               1031                 :                :         {
 8121                          1032                 :             54 :             name = getoffset(name, &dstoffset);
                               1033         [ -  + ]:             54 :             if (name == NULL)
 3771 tgl@sss.pgh.pa.us        1034                 :UBC           0 :                 return false;
                               1035                 :                :         }
                               1036                 :                :         else
 8100 bruce@momjian.us         1037                 :CBC        6510 :             dstoffset = stdoffset - SECSPERHOUR;
                               1038                 :                : 
   24 tgl@sss.pgh.pa.us        1039         [ +  + ]:GNC        6564 :         if (*name == '\0')
                               1040                 :              4 :             name = TZDEFRULESTRING;
                               1041   [ -  +  -  - ]:           6564 :         if (!(*name == ',' || *name == ';'))
   24 tgl@sss.pgh.pa.us        1042                 :UNC           0 :             return false;
                               1043                 :                : 
   24 tgl@sss.pgh.pa.us        1044                 :GNC        6564 :         name = getrule(name + 1, &start);
                               1045         [ -  + ]:           6564 :         if (!name)
   24 tgl@sss.pgh.pa.us        1046                 :UNC           0 :             return false;
   24 tgl@sss.pgh.pa.us        1047         [ -  + ]:GNC        6564 :         if (*name++ != ',')
   24 tgl@sss.pgh.pa.us        1048                 :UNC           0 :             return false;
   24 tgl@sss.pgh.pa.us        1049                 :GNC        6564 :         name = getrule(name, &end);
                               1050   [ +  -  -  + ]:           6564 :         if (!name || *name)
   24 tgl@sss.pgh.pa.us        1051                 :UNC           0 :             return false;
   24 tgl@sss.pgh.pa.us        1052                 :GNC        6564 :         sp->typecnt = 2;     /* standard time and DST */
                               1053                 :                : 
                               1054                 :                :         /*
                               1055                 :                :          * Two transitions per year, from EPOCH_YEAR forward.
                               1056                 :                :          */
                               1057                 :           6564 :         init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
                               1058                 :           6564 :         init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
                               1059                 :           6564 :         timecnt = 0;
                               1060                 :           6564 :         janfirst = 0;
                               1061                 :           6564 :         yearbeg = EPOCH_YEAR;
                               1062                 :                : 
                               1063                 :                :         do
                               1064                 :                :         {
                               1065                 :           9151 :             int_fast32_t yearsecs
                               1066   [ +  +  +  +  :           9151 :             = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
                                              -  + ]
                               1067                 :           9151 :             pg_time_t   janfirst1 = janfirst;
                               1068                 :                : 
                               1069                 :           9151 :             yearbeg--;
                               1070         [ -  + ]:           9151 :             if (increment_overflow_time(&janfirst1, -yearsecs))
                               1071                 :                :             {
   24 tgl@sss.pgh.pa.us        1072                 :UNC           0 :                 janoffset = -yearsecs;
                               1073                 :              0 :                 break;
                               1074                 :                :             }
   24 tgl@sss.pgh.pa.us        1075                 :GNC        9151 :             janfirst = janfirst1;
                               1076                 :           9151 :         } while (atlo < janfirst
                               1077   [ +  +  +  + ]:           9151 :                  && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
                               1078                 :                : 
                               1079                 :                :         while (true)
 8100 bruce@momjian.us         1080                 :GIC      246131 :         {
   24 tgl@sss.pgh.pa.us        1081                 :GNC      252695 :             int_fast32_t yearsecs
                               1082   [ +  +  +  +  :         252695 :             = year_lengths[isleap(yearbeg)] * SECSPERDAY;
                                              +  - ]
                               1083                 :         252695 :             int         yearbeg1 = yearbeg;
                               1084                 :         252695 :             pg_time_t   janfirst1 = janfirst;
                               1085                 :                : 
                               1086         [ +  - ]:         252695 :             if (increment_overflow_time(&janfirst1, yearsecs)
                               1087         [ +  - ]:         252695 :                 || increment_overflow(&yearbeg1, 1)
                               1088         [ +  + ]:         252695 :                 || atlo <= janfirst1)
                               1089                 :                :                 break;
                               1090                 :         246131 :             yearbeg = yearbeg1;
                               1091                 :         246131 :             janfirst = janfirst1;
                               1092                 :                :         }
                               1093                 :                : 
                               1094                 :           6564 :         yearlim = yearbeg;
                               1095         [ -  + ]:           6564 :         if (increment_overflow(&yearlim, years_of_observations))
   24 tgl@sss.pgh.pa.us        1096                 :UNC           0 :             yearlim = INT_MAX;
   24 tgl@sss.pgh.pa.us        1097         [ +  + ]:GNC     2645292 :         for (year = yearbeg; year < yearlim; year++)
                               1098                 :                :         {
                               1099                 :                :             int_fast32_t
                               1100                 :        2638728 :                         starttime = transtime(year, &start, stdoffset),
                               1101                 :        2638728 :                         endtime = transtime(year, &end, dstoffset),
                               1102   [ +  +  +  +  :        2638728 :                         yearsecs = year_lengths[isleap(year)] * SECSPERDAY;
                                              +  + ]
                               1103                 :        2638728 :             bool        reversed = endtime < starttime;
                               1104                 :                : 
                               1105         [ +  + ]:        2638728 :             if (reversed)
                               1106                 :                :             {
                               1107                 :         123012 :                 int_fast32_t swap = starttime;
                               1108                 :                : 
                               1109                 :         123012 :                 starttime = endtime;
                               1110                 :         123012 :                 endtime = swap;
                               1111                 :                :             }
                               1112         [ +  + ]:        2638728 :             if (reversed
                               1113         [ +  - ]:        2515716 :                 || (starttime < endtime
                               1114         [ +  - ]:        2515716 :                     && endtime - starttime < yearsecs))
                               1115                 :                :             {
                               1116         [ -  + ]:        2638728 :                 if (TZ_MAX_TIMES - 2 < timecnt)
 8121 bruce@momjian.us         1117                 :UBC           0 :                     break;
   24 tgl@sss.pgh.pa.us        1118                 :GNC     2638728 :                 sp->ats[timecnt] = janfirst;
                               1119         [ +  - ]:        2638728 :                 if (!increment_overflow_time(&sp->ats[timecnt],
                               1120                 :                :                                              janoffset + starttime)
                               1121         [ +  + ]:        2638728 :                     && atlo <= sp->ats[timecnt])
                               1122                 :        2638270 :                     sp->types[timecnt++] = !reversed;
                               1123                 :        2638728 :                 sp->ats[timecnt] = janfirst;
                               1124         [ +  - ]:        2638728 :                 if (!increment_overflow_time(&sp->ats[timecnt],
                               1125                 :                :                                              janoffset + endtime)
                               1126         [ +  + ]:        2638728 :                     && atlo <= sp->ats[timecnt])
                               1127                 :                :                 {
                               1128                 :        2638540 :                     sp->types[timecnt++] = reversed;
                               1129                 :                :                 }
                               1130                 :                :             }
                               1131         [ -  + ]:        2638728 :             if (endtime < leaplo)
                               1132                 :                :             {
   24 tgl@sss.pgh.pa.us        1133                 :UNC           0 :                 yearlim = year;
                               1134         [ #  # ]:              0 :                 if (increment_overflow(&yearlim, years_of_observations))
                               1135                 :              0 :                     yearlim = INT_MAX;
                               1136                 :                :             }
   24 tgl@sss.pgh.pa.us        1137         [ -  + ]:GNC     2638728 :             if (increment_overflow_time(&janfirst, janoffset + yearsecs))
   24 tgl@sss.pgh.pa.us        1138                 :UNC           0 :                 break;
   24 tgl@sss.pgh.pa.us        1139                 :GNC     2638728 :             janoffset = 0;
                               1140                 :                :         }
                               1141                 :           6564 :         sp->timecnt = timecnt;
                               1142         [ -  + ]:           6564 :         if (!timecnt)
                               1143                 :                :         {
   24 tgl@sss.pgh.pa.us        1144                 :UNC           0 :             sp->ttis[0] = sp->ttis[1];
                               1145                 :              0 :             sp->typecnt = 1; /* Perpetual DST.  */
                               1146                 :                :         }
   24 tgl@sss.pgh.pa.us        1147         [ +  - ]:GNC        6564 :         else if (years_of_observations <= year - yearbeg)
                               1148                 :           6564 :             sp->goback = sp->goahead = true;
                               1149                 :                :     }
                               1150                 :                :     else
                               1151                 :                :     {
 8121 bruce@momjian.us         1152                 :CBC        7115 :         dstlen = 0;
                               1153                 :           7115 :         sp->typecnt = 1;     /* only standard time */
                               1154                 :           7115 :         sp->timecnt = 0;
 3771 tgl@sss.pgh.pa.us        1155                 :           7115 :         init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
                               1156                 :                :     }
                               1157                 :          13679 :     sp->charcnt = charcnt;
 8121 bruce@momjian.us         1158                 :          13679 :     cp = sp->chars;
 3771 tgl@sss.pgh.pa.us        1159                 :          13679 :     memcpy(cp, stdname, stdlen);
 8121 bruce@momjian.us         1160                 :          13679 :     cp += stdlen;
                               1161                 :          13679 :     *cp++ = '\0';
 8100                          1162         [ +  + ]:          13679 :     if (dstlen != 0)
                               1163                 :                :     {
 3771 tgl@sss.pgh.pa.us        1164                 :           6564 :         memcpy(cp, dstname, dstlen);
   24 tgl@sss.pgh.pa.us        1165                 :GNC        6564 :         cp += dstlen;
                               1166                 :           6564 :         *cp = '\0';
                               1167                 :                :     }
 3771 tgl@sss.pgh.pa.us        1168                 :CBC       13679 :     return true;
                               1169                 :                : }
                               1170                 :                : 
                               1171                 :                : static void
 2836                          1172                 :           1487 : gmtload(struct state *const sp)
                               1173                 :                : {
                               1174                 :                :     /* PG: for historical compatibility, use "GMT" not "UTC" as TZ abbrev */
   24 tgl@sss.pgh.pa.us        1175                 :GNC        1487 :     tzparse("GMT0", sp, NULL);
 8121 bruce@momjian.us         1176                 :CBC        1487 : }
                               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 *
 3321 tgl@sss.pgh.pa.us        1186                 :         823066 : 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;
 8087                          1192                 :         823066 :     const pg_time_t t = *timep;
                               1193                 :                : 
 3771                          1194         [ -  + ]:         823066 :     if (sp == NULL)
 3771 tgl@sss.pgh.pa.us        1195                 :UBC           0 :         return gmtsub(timep, 0, tmp);
 6734 tgl@sss.pgh.pa.us        1196   [ +  +  +  - ]:CBC      823066 :     if ((sp->goback && t < sp->ats[0]) ||
                               1197   [ +  +  +  + ]:         823066 :         (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])
 6734 tgl@sss.pgh.pa.us        1204                 :UBC           0 :             seconds = sp->ats[0] - t;
                               1205                 :                :         else
 6253 bruce@momjian.us         1206                 :CBC          44 :             seconds = t - sp->ats[sp->timecnt - 1];
 6734 tgl@sss.pgh.pa.us        1207                 :             44 :         --seconds;
                               1208                 :                : 
                               1209                 :                :         /*
                               1210                 :                :          * Beware integer overflow, as SECONDS might be close to the maximum
                               1211                 :                :          * pg_time_t.
                               1212                 :                :          */
   24 tgl@sss.pgh.pa.us        1213                 :GNC          44 :         years = seconds / SECSPERREPEAT * YEARSPERREPEAT;
 3771 tgl@sss.pgh.pa.us        1214                 :CBC          44 :         seconds = years * AVGSECSPERYEAR;
   24 tgl@sss.pgh.pa.us        1215                 :GNC          44 :         years += YEARSPERREPEAT;
 6734 tgl@sss.pgh.pa.us        1216         [ -  + ]:CBC          44 :         if (t < sp->ats[0])
   24 tgl@sss.pgh.pa.us        1217                 :UNC           0 :             newt = t + seconds + SECSPERREPEAT;
                               1218                 :                :         else
   24 tgl@sss.pgh.pa.us        1219                 :GNC          44 :             newt = t - seconds - SECSPERREPEAT;
                               1220                 :                : 
 6734 tgl@sss.pgh.pa.us        1221         [ +  - ]:CBC          44 :         if (newt < sp->ats[0] ||
                               1222         [ -  + ]:             44 :             newt > sp->ats[sp->timecnt - 1])
 6253 bruce@momjian.us         1223                 :UBC           0 :             return NULL;        /* "cannot happen" */
 3771 tgl@sss.pgh.pa.us        1224                 :CBC          44 :         result = localsub(sp, &newt, tmp);
                               1225         [ +  - ]:             44 :         if (result)
                               1226                 :                :         {
                               1227                 :                : #if defined ckd_add && defined ckd_sub
   24 tgl@sss.pgh.pa.us        1228   [ -  +  -  + ]:GNC          88 :             if (t < sp->ats[0]
   24 tgl@sss.pgh.pa.us        1229                 :UNC           0 :                 ? ckd_sub(&result->tm_year,
                               1230                 :                :                           result->tm_year, years)
   24 tgl@sss.pgh.pa.us        1231                 :GNC          44 :                 : ckd_add(&result->tm_year,
                               1232                 :                :                           result->tm_year, years))
   24 tgl@sss.pgh.pa.us        1233                 :UNC           0 :                 return NULL;
                               1234                 :                : #else
                               1235                 :                :             int_fast64_t newy;
                               1236                 :                : 
 3771 tgl@sss.pgh.pa.us        1237                 :ECB        (44) :             newy = result->tm_year;
 6734                          1238         [ -  + ]:           (44) :             if (t < sp->ats[0])
 3771 tgl@sss.pgh.pa.us        1239                 :EUB             :                 newy -= years;
                               1240                 :                :             else
 3771 tgl@sss.pgh.pa.us        1241                 :ECB        (44) :                 newy += years;
                               1242   [ +  -  -  + ]:           (44) :             if (!(INT_MIN <= newy && newy <= INT_MAX))
 6734 tgl@sss.pgh.pa.us        1243                 :EUB             :                 return NULL;
 3771 tgl@sss.pgh.pa.us        1244                 :ECB        (44) :             result->tm_year = newy;
                               1245                 :                : #endif
                               1246                 :                :         }
 6734 tgl@sss.pgh.pa.us        1247                 :CBC          44 :         return result;
                               1248                 :                :     }
 8100 bruce@momjian.us         1249   [ +  +  +  + ]:         823022 :     if (sp->timecnt == 0 || t < sp->ats[0])
                               1250                 :                :     {
   24 tgl@sss.pgh.pa.us        1251                 :GNC      743494 :         i = 0;
                               1252                 :                :     }
                               1253                 :                :     else
                               1254                 :                :     {
 6253 bruce@momjian.us         1255                 :CBC       79528 :         int         lo = 1;
                               1256                 :          79528 :         int         hi = sp->timecnt;
                               1257                 :                : 
 6734 tgl@sss.pgh.pa.us        1258         [ +  + ]:         820285 :         while (lo < hi)
                               1259                 :                :         {
 6253 bruce@momjian.us         1260                 :         740757 :             int         mid = (lo + hi) >> 1;
                               1261                 :                : 
 6734 tgl@sss.pgh.pa.us        1262         [ +  + ]:         740757 :             if (t < sp->ats[mid])
                               1263                 :         429214 :                 hi = mid;
                               1264                 :                :             else
 6253 bruce@momjian.us         1265                 :         311543 :                 lo = mid + 1;
                               1266                 :                :         }
   24 tgl@sss.pgh.pa.us        1267                 :GNC       79528 :         i = sp->types[lo - 1];
                               1268                 :                :     }
 8121 bruce@momjian.us         1269                 :CBC      823022 :     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                 :                :      */
 2565 tgl@sss.pgh.pa.us        1276                 :         823022 :     result = timesub(&t, ttisp->tt_utoff, sp, tmp);
 3771                          1277         [ +  - ]:         823022 :     if (result)
                               1278                 :                :     {
                               1279                 :         823022 :         result->tm_isdst = ttisp->tt_isdst;
                               1280                 :                : #ifdef TM_ZONE
   24 tgl@sss.pgh.pa.us        1281                 :GNC      823022 :         result->TM_ZONE = UNCONST(&sp->chars[ttisp->tt_desigidx]);
                               1282                 :                : #endif
                               1283                 :                :     }
 6734 tgl@sss.pgh.pa.us        1284                 :CBC      823022 :     return result;
                               1285                 :                : }
                               1286                 :                : 
                               1287                 :                : 
                               1288                 :                : struct pg_tm *
 7767 bruce@momjian.us         1289                 :         823022 : pg_localtime(const pg_time_t *timep, const pg_tz *tz)
                               1290                 :                : {
 3771 tgl@sss.pgh.pa.us        1291                 :         823022 :     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 *
   24 tgl@sss.pgh.pa.us        1302                 :GNC      202929 : 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                 :                : 
 2839 tgl@sss.pgh.pa.us        1310         [ +  + ]:CBC      202929 :     if (gmtptr == NULL)
                               1311                 :                :     {
                               1312                 :                :         /* Allocate on first use */
                               1313                 :            212 :         gmtptr = (struct state *) malloc(sizeof(struct state));
                               1314         [ -  + ]:            212 :         if (gmtptr == NULL)
 2839 tgl@sss.pgh.pa.us        1315                 :UBC           0 :             return NULL;        /* errno should be set by malloc */
 8100 tgl@sss.pgh.pa.us        1316                 :CBC         212 :         gmtload(gmtptr);
                               1317                 :                :     }
                               1318                 :                : 
 6734                          1319                 :         202929 :     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                 :                :      */
   24 tgl@sss.pgh.pa.us        1326         [ +  - ]:GNC      202929 :     tmp->TM_ZONE = UNCONST(offset ? wildabbr
                               1327                 :                :                            : gmtptr->chars);
                               1328                 :                : #endif                          /* defined TM_ZONE */
 6734 tgl@sss.pgh.pa.us        1329                 :CBC      202929 :     return result;
                               1330                 :                : }
                               1331                 :                : 
                               1332                 :                : struct pg_tm *
 8087                          1333                 :         202929 : pg_gmtime(const pg_time_t *timep)
                               1334                 :                : {
 3771                          1335                 :         202929 :     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
   24 tgl@sss.pgh.pa.us        1344                 :GNC     4288780 : leaps_thru_end_of_nonneg(pg_time_t y)
                               1345                 :                : {
 3228 tgl@sss.pgh.pa.us        1346                 :CBC     4288780 :     return y / 4 - y / 100 + y / 400;
                               1347                 :                : }
                               1348                 :                : 
                               1349                 :                : static pg_time_t
   24 tgl@sss.pgh.pa.us        1350                 :GNC     4288780 : leaps_thru_end_of(pg_time_t y)
                               1351                 :                : {
                               1352                 :                :     return (y < 0
 3228 tgl@sss.pgh.pa.us        1353                 :CBC        1496 :             ? -1 - leaps_thru_end_of_nonneg(-1 - y)
                               1354         [ +  + ]:        4290276 :             : leaps_thru_end_of_nonneg(y));
                               1355                 :                : }
                               1356                 :                : 
                               1357                 :                : static struct pg_tm *
  246 peter@eisentraut.org     1358                 :        1025951 : 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                 :                :      */
   24 tgl@sss.pgh.pa.us        1376                 :GNC     1025951 :     pg_time_t   secs_since_posleap = SECSPERMIN;
                               1377                 :                : 
 8121 bruce@momjian.us         1378                 :CBC     1025951 :     corr = 0;
   24 tgl@sss.pgh.pa.us        1379         [ +  - ]:GNC     1025951 :     i = sp ? leapcount(sp) : 0;
 8100 bruce@momjian.us         1380         [ -  + ]:CBC     1025951 :     while (--i >= 0)
                               1381                 :                :     {
   24 tgl@sss.pgh.pa.us        1382                 :UNC           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;
 8121 bruce@momjian.us         1389                 :UBC           0 :             break;
                               1390                 :                :         }
                               1391                 :                :     }
                               1392                 :                : 
                               1393                 :                :     /*
                               1394                 :                :      * Calculate the year, avoiding integer overflow even if pg_time_t is
                               1395                 :                :      * unsigned.
                               1396                 :                :      */
 6734 tgl@sss.pgh.pa.us        1397                 :CBC     1025951 :     tdays = *timep / SECSPERDAY;
 3771                          1398                 :        1025951 :     rem = *timep % SECSPERDAY;
   24 tgl@sss.pgh.pa.us        1399                 :GNC     1025951 :     rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
                               1400                 :        1025951 :     dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
                               1401                 :        1025951 :     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                 :        1025951 :     dayrem = tdays % DAYSPERREPEAT;
                               1410                 :        1025951 :     dayrem += dayoff % DAYSPERREPEAT;
                               1411                 :        1025951 :     y = (EPOCH_YEAR - YEARSPERREPEAT
                               1412                 :        1025951 :          + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
                               1413                 :        1025951 :              - ((dayrem % DAYSPERREPEAT) < 0)
                               1414                 :        1025951 :              + tdays / DAYSPERREPEAT)
                               1415                 :                :             * YEARSPERREPEAT));
                               1416                 :                :     /* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow.  */
                               1417                 :        1025951 :     idays = tdays % DAYSPERREPEAT;
                               1418                 :        1025951 :     idays += dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT;
                               1419                 :        1025951 :     idays %= DAYSPERREPEAT;
                               1420                 :                :     /* Increase Y and decrease IDAYS until IDAYS is in range for Y.  */
                               1421   [ +  +  +  +  :        2144390 :     while (year_lengths[isleap(y)] <= idays)
                                        +  +  +  + ]
                               1422                 :                :     {
                               1423                 :        1118439 :         int         tdelta = idays / DAYSPERLYEAR;
                               1424                 :        1118439 :         int_fast32_t ydelta = tdelta + !tdelta;
                               1425                 :        1118439 :         pg_time_t   newy = y + ydelta;
                               1426                 :                :         int         leapdays;
                               1427                 :                : 
 6734 tgl@sss.pgh.pa.us        1428                 :CBC     1118439 :         leapdays = leaps_thru_end_of(newy - 1) -
                               1429                 :        1118439 :             leaps_thru_end_of(y - 1);
   24 tgl@sss.pgh.pa.us        1430                 :GNC     1118439 :         idays -= ydelta * DAYSPERNYEAR;
                               1431                 :        1118439 :         idays -= leapdays;
 6734 tgl@sss.pgh.pa.us        1432                 :CBC     1118439 :         y = newy;
                               1433                 :                :     }
                               1434                 :                : 
                               1435                 :                : #ifdef ckd_add
   24 tgl@sss.pgh.pa.us        1436         [ -  + ]:GNC     1025951 :     if (ckd_add(&tmp->tm_year, y, -TM_YEAR_BASE))
                               1437                 :                :     {
   24 tgl@sss.pgh.pa.us        1438                 :UNC           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
 6734 tgl@sss.pgh.pa.us        1457                 :CBC     1025951 :     tmp->tm_yday = idays;
                               1458                 :                : 
                               1459                 :                :     /*
                               1460                 :                :      * The "extra" mods below avoid overflow problems.
                               1461                 :                :      */
   24 tgl@sss.pgh.pa.us        1462                 :GNC     1025951 :     tmp->tm_wday = (TM_WDAY_BASE
                               1463                 :        1025951 :                     + ((tmp->tm_year % DAYSPERWEEK)
                               1464                 :        1025951 :                        * (DAYSPERNYEAR % DAYSPERWEEK))
                               1465                 :        1025951 :                     + leaps_thru_end_of(y - 1)
                               1466                 :        1025951 :                     - leaps_thru_end_of(TM_YEAR_BASE - 1)
                               1467                 :        1025951 :                     + idays);
 6734 tgl@sss.pgh.pa.us        1468                 :CBC     1025951 :     tmp->tm_wday %= DAYSPERWEEK;
 8121 bruce@momjian.us         1469         [ +  + ]:        1025951 :     if (tmp->tm_wday < 0)
                               1470                 :           1093 :         tmp->tm_wday += DAYSPERWEEK;
   24 tgl@sss.pgh.pa.us        1471                 :GNC     1025951 :     tmp->tm_hour = rem / SECSPERHOUR;
 6734 tgl@sss.pgh.pa.us        1472                 :CBC     1025951 :     rem %= SECSPERHOUR;
   24 tgl@sss.pgh.pa.us        1473                 :GNC     1025951 :     tmp->tm_min = rem / SECSPERMIN;
                               1474                 :        1025951 :     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                 :        1025951 :     tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
                               1481                 :                : 
 6734 tgl@sss.pgh.pa.us        1482   [ +  +  +  +  :CBC     1025951 :     ip = mon_lengths[isleap(y)];
                                              +  + ]
                               1483         [ +  + ]:        6629642 :     for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
                               1484                 :        5603691 :         idays -= ip[tmp->tm_mon];
   24 tgl@sss.pgh.pa.us        1485                 :GNC     1025951 :     tmp->tm_mday = idays + 1;
 8121 bruce@momjian.us         1486                 :CBC     1025951 :     tmp->tm_isdst = 0;
                               1487                 :                : #ifdef TM_GMTOFF
   24 tgl@sss.pgh.pa.us        1488                 :GNC     1025951 :     tmp->TM_GMTOFF = offset;
                               1489                 :                : #endif                          /* defined TM_GMTOFF */
 6734 tgl@sss.pgh.pa.us        1490                 :CBC     1025951 :     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
 3771                          1511                 :         259259 : increment_overflow(int *ip, int j)
                               1512                 :                : {
                               1513                 :                : #ifdef ckd_add
   24 tgl@sss.pgh.pa.us        1514                 :GNC      259259 :     return ckd_add(ip, *ip, j);
                               1515                 :                : #else
 3771 tgl@sss.pgh.pa.us        1516                 :ECB   (2182647) :     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   [ +  +  -  + ]:      (2182647) :     if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
 3771 tgl@sss.pgh.pa.us        1526                 :EUB             :         return true;
 3771 tgl@sss.pgh.pa.us        1527                 :ECB   (2182647) :     *ip += j;
                               1528                 :      (2182647) :     return false;
                               1529                 :                : #endif
                               1530                 :                : }
                               1531                 :                : 
                               1532                 :                : static bool
   24 tgl@sss.pgh.pa.us        1533                 :GNC    13444388 : increment_overflow_time(pg_time_t *tp, int_fast32_2s j)
                               1534                 :                : {
                               1535                 :                : #ifdef ckd_add
                               1536                 :       13444388 :     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                 :                :      */
 3771 tgl@sss.pgh.pa.us        1544   [ +  +  -  + ]:ECB  (42022400) :     if (!(j < 0
 3228                          1545                 :      (1313200) :           ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
                               1546                 :     (19698000) :           : *tp <= TIME_T_MAX - j))
 3771 tgl@sss.pgh.pa.us        1547                 :EUB             :         return true;
 3771 tgl@sss.pgh.pa.us        1548                 :ECB  (21011200) :     *tp += j;
                               1549                 :     (21011200) :     return false;
                               1550                 :                : #endif
                               1551                 :                : }
                               1552                 :                : 
                               1553                 :                : static int_fast32_2s
 2229 tgl@sss.pgh.pa.us        1554                 :CBC     5266358 : leapcorr(struct state const *sp, pg_time_t t)
                               1555                 :                : {
                               1556                 :                :     int         i;
                               1557                 :                : 
   24 tgl@sss.pgh.pa.us        1558                 :GNC     5266358 :     i = leapcount(sp);
 2229 tgl@sss.pgh.pa.us        1559         [ -  + ]:CBC     5266358 :     while (--i >= 0)
                               1560                 :                :     {
   24 tgl@sss.pgh.pa.us        1561                 :UNC           0 :         struct lsinfo ls = lsinfo(sp, i);
                               1562                 :                : 
                               1563         [ #  # ]:              0 :         if (ls.ls_trans <= t)
                               1564                 :              0 :             return ls.ls_corr;
                               1565                 :                :     }
 2229 tgl@sss.pgh.pa.us        1566                 :CBC     5266358 :     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
   24 tgl@sss.pgh.pa.us        1590                 :GNC       13649 : pg_tzload(const char *name, char *canonname, struct state *sp)
                               1591                 :                : {
                               1592         [ +  + ]:          13649 :     if (strcmp(name, "GMT") == 0)
                               1593                 :                :     {
                               1594                 :           1275 :         gmtload(sp);
                               1595                 :                :         /* Use given name as canonical */
                               1596         [ +  + ]:           1275 :         if (canonname)
                               1597                 :           1265 :             strcpy(canonname, name);
                               1598                 :                :     }
                               1599         [ +  + ]:          12374 :     else if (tzload(name, canonname, sp, TZLOAD_TZSTRING) != 0)
                               1600                 :                :     {
                               1601   [ +  -  +  + ]:            403 :         if (name[0] == ':' || !tzparse(name, sp, NULL))
                               1602                 :                :         {
                               1603                 :                :             /* Unknown timezone. Fail our call instead of loading GMT! */
                               1604                 :            182 :             return false;
                               1605                 :                :         }
                               1606                 :                :         /* For POSIX timezone specs, use given name as canonical */
                               1607         [ +  - ]:            221 :         if (canonname)
                               1608                 :            221 :             strcpy(canonname, name);
                               1609                 :                :     }
                               1610                 :          13467 :     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
 7936 tgl@sss.pgh.pa.us        1634                 :CBC      110464 : 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                 :         110464 :     const pg_time_t t = *timep;
                               1647                 :                : 
 7767 bruce@momjian.us         1648                 :         110464 :     sp = &tz->state;
 7936 tgl@sss.pgh.pa.us        1649         [ +  + ]:         110464 :     if (sp->timecnt == 0)
                               1650                 :                :     {
                               1651                 :                :         /* non-DST zone, use the defaulttype (now always 0) */
   24 tgl@sss.pgh.pa.us        1652                 :GNC        2631 :         ttisp = &sp->ttis[0];
 2565 tgl@sss.pgh.pa.us        1653                 :CBC        2631 :         *before_gmtoff = ttisp->tt_utoff;
 7936                          1654                 :           2631 :         *before_isdst = ttisp->tt_isdst;
                               1655                 :           2631 :         return 0;
                               1656                 :                :     }
 6734                          1657   [ +  +  +  - ]:         107833 :     if ((sp->goback && t < sp->ats[0]) ||
                               1658   [ +  +  +  + ]:         107833 :         (sp->goahead && t > sp->ats[sp->timecnt - 1]))
                               1659                 :                :     {
                               1660                 :                :         /* For values outside the transition table, extrapolate */
                               1661                 :          34064 :         pg_time_t   newt = t;
                               1662                 :                :         pg_time_t   seconds;
                               1663                 :                :         pg_time_t   tcycles;
                               1664                 :                :         int64       icycles;
                               1665                 :                :         int         result;
                               1666                 :                : 
                               1667         [ -  + ]:          34064 :         if (t < sp->ats[0])
 6734 tgl@sss.pgh.pa.us        1668                 :UBC           0 :             seconds = sp->ats[0] - t;
                               1669                 :                :         else
 6253 bruce@momjian.us         1670                 :CBC       34064 :             seconds = t - sp->ats[sp->timecnt - 1];
 6734 tgl@sss.pgh.pa.us        1671                 :          34064 :         --seconds;
                               1672                 :          34064 :         tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
                               1673                 :          34064 :         ++tcycles;
                               1674                 :          34064 :         icycles = tcycles;
                               1675   [ +  -  -  + ]:          34064 :         if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
 6734 tgl@sss.pgh.pa.us        1676                 :UBC           0 :             return -1;
 6734 tgl@sss.pgh.pa.us        1677                 :CBC       34064 :         seconds = icycles;
                               1678                 :          34064 :         seconds *= YEARSPERREPEAT;
                               1679                 :          34064 :         seconds *= AVGSECSPERYEAR;
                               1680         [ -  + ]:          34064 :         if (t < sp->ats[0])
 6734 tgl@sss.pgh.pa.us        1681                 :UBC           0 :             newt += seconds;
                               1682                 :                :         else
 6253 bruce@momjian.us         1683                 :CBC       34064 :             newt -= seconds;
 6734 tgl@sss.pgh.pa.us        1684         [ +  - ]:          34064 :         if (newt < sp->ats[0] ||
                               1685         [ -  + ]:          34064 :             newt > sp->ats[sp->timecnt - 1])
 6253 bruce@momjian.us         1686                 :UBC           0 :             return -1;          /* "cannot happen" */
                               1687                 :                : 
 6734 tgl@sss.pgh.pa.us        1688                 :CBC       34064 :         result = pg_next_dst_boundary(&newt, before_gmtoff,
                               1689                 :                :                                       before_isdst,
                               1690                 :                :                                       boundary,
                               1691                 :                :                                       after_gmtoff,
                               1692                 :                :                                       after_isdst,
                               1693                 :                :                                       tz);
                               1694         [ -  + ]:          34064 :         if (t < sp->ats[0])
 6734 tgl@sss.pgh.pa.us        1695                 :UBC           0 :             *boundary -= seconds;
                               1696                 :                :         else
 6734 tgl@sss.pgh.pa.us        1697                 :CBC       34064 :             *boundary += seconds;
                               1698                 :          34064 :         return result;
                               1699                 :                :     }
                               1700                 :                : 
 5204                          1701         [ +  + ]:          73769 :     if (t >= sp->ats[sp->timecnt - 1])
                               1702                 :                :     {
                               1703                 :                :         /* No known transition > t, so use last known segment's type */
 7936                          1704                 :            720 :         i = sp->types[sp->timecnt - 1];
                               1705                 :            720 :         ttisp = &sp->ttis[i];
 2565                          1706                 :            720 :         *before_gmtoff = ttisp->tt_utoff;
 7936                          1707                 :            720 :         *before_isdst = ttisp->tt_isdst;
                               1708                 :            720 :         return 0;
                               1709                 :                :     }
 5204                          1710         [ +  + ]:          73049 :     if (t < sp->ats[0])
                               1711                 :                :     {
                               1712                 :                :         /* For "before", use the defaulttype (now always 0) */
   24 tgl@sss.pgh.pa.us        1713                 :GNC         384 :         ttisp = &sp->ttis[0];
 2565 tgl@sss.pgh.pa.us        1714                 :CBC         384 :         *before_gmtoff = ttisp->tt_utoff;
 7936                          1715                 :            384 :         *before_isdst = ttisp->tt_isdst;
                               1716                 :            384 :         *boundary = sp->ats[0];
                               1717                 :                :         /* And for "after", use the first segment's type */
                               1718                 :            384 :         i = sp->types[0];
                               1719                 :            384 :         ttisp = &sp->ttis[i];
 2565                          1720                 :            384 :         *after_gmtoff = ttisp->tt_utoff;
 7936                          1721                 :            384 :         *after_isdst = ttisp->tt_isdst;
                               1722                 :            384 :         return 1;
                               1723                 :                :     }
                               1724                 :                :     /* Else search to find the boundary following t */
                               1725                 :                :     {
 6253 bruce@momjian.us         1726                 :          72665 :         int         lo = 1;
 5204 tgl@sss.pgh.pa.us        1727                 :          72665 :         int         hi = sp->timecnt - 1;
                               1728                 :                : 
 6734                          1729         [ +  + ]:         791074 :         while (lo < hi)
                               1730                 :                :         {
 6253 bruce@momjian.us         1731                 :         718409 :             int         mid = (lo + hi) >> 1;
                               1732                 :                : 
 6734 tgl@sss.pgh.pa.us        1733         [ +  + ]:         718409 :             if (t < sp->ats[mid])
                               1734                 :         407271 :                 hi = mid;
                               1735                 :                :             else
 6253 bruce@momjian.us         1736                 :         311138 :                 lo = mid + 1;
                               1737                 :                :         }
 6734 tgl@sss.pgh.pa.us        1738                 :          72665 :         i = lo;
                               1739                 :                :     }
 7936                          1740                 :          72665 :     j = sp->types[i - 1];
                               1741                 :          72665 :     ttisp = &sp->ttis[j];
 2565                          1742                 :          72665 :     *before_gmtoff = ttisp->tt_utoff;
 7936                          1743                 :          72665 :     *before_isdst = ttisp->tt_isdst;
                               1744                 :          72665 :     *boundary = sp->ats[i];
                               1745                 :          72665 :     j = sp->types[i];
                               1746                 :          72665 :     ttisp = &sp->ttis[j];
 2565                          1747                 :          72665 :     *after_gmtoff = ttisp->tt_utoff;
 7936                          1748                 :          72665 :     *after_isdst = ttisp->tt_isdst;
                               1749                 :          72665 :     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
 4300                          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)
 3771                          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                 :                :     {
 4300                          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]];
 2565                          1833         [ +  + ]:          13682 :         if (ttisp->tt_desigidx == abbrind)
                               1834                 :                :         {
                               1835                 :            326 :             *gmtoff = ttisp->tt_utoff;
 4300                          1836                 :            326 :             *isdst = ttisp->tt_isdst;
 3771                          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                 :                :      */
   24 tgl@sss.pgh.pa.us        1845                 :GNC          28 :     ttisp = &sp->ttis[0];
  555 tgl@sss.pgh.pa.us        1846         [ +  - ]:CBC          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                 :                :      */
 4300 tgl@sss.pgh.pa.us        1856         [ #  # ]:UBC           0 :     for (i = cutoff; i < sp->timecnt; i++)
                               1857                 :                :     {
                               1858                 :              0 :         ttisp = &sp->ttis[sp->types[i]];
 2565                          1859         [ #  # ]:              0 :         if (ttisp->tt_desigidx == abbrind)
                               1860                 :                :         {
                               1861                 :              0 :             *gmtoff = ttisp->tt_utoff;
 4300                          1862                 :              0 :             *isdst = ttisp->tt_isdst;
 3771                          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
  555 tgl@sss.pgh.pa.us        1885                 :CBC        4139 : 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                 :           4139 :     bool        result = false;
                               1892                 :           4139 :     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                 :           4139 :     abbrs = sp->chars;
                               1901                 :           4139 :     abbrind = 0;
                               1902         [ +  + ]:          23501 :     while (abbrind < sp->charcnt)
                               1903                 :                :     {
                               1904         [ +  + ]:          19494 :         if (strcmp(abbrev, abbrs + abbrind) == 0)
                               1905                 :            132 :             break;
                               1906         [ +  + ]:          77488 :         while (abbrs[abbrind] != '\0')
                               1907                 :          58126 :             abbrind++;
                               1908                 :          19362 :         abbrind++;
                               1909                 :                :     }
                               1910         [ +  + ]:           4139 :     if (abbrind >= sp->charcnt)
                               1911                 :           4007 :         return false;           /* definitely not there */
                               1912                 :                : 
                               1913                 :                :     /*
                               1914                 :                :      * Scan the ttinfo array to find uses of the abbreviation.
                               1915                 :                :      */
                               1916         [ +  + ]:           1043 :     for (int i = 0; i < sp->typecnt; i++)
                               1917                 :                :     {
                               1918                 :            911 :         const struct ttinfo *ttisp = &sp->ttis[i];
                               1919                 :                : 
                               1920         [ +  + ]:            911 :         if (ttisp->tt_desigidx == abbrind)
                               1921                 :                :         {
                               1922         [ +  + ]:            248 :             if (!result)
                               1923                 :                :             {
                               1924                 :                :                 /* First usage */
                               1925                 :            132 :                 *isfixed = true;    /* for the moment */
                               1926                 :            132 :                 *gmtoff = ttisp->tt_utoff;
                               1927                 :            132 :                 *isdst = ttisp->tt_isdst;
                               1928                 :            132 :                 result = true;
                               1929                 :                :             }
                               1930                 :                :             else
                               1931                 :                :             {
                               1932                 :                :                 /* Second or later usage, does it match? */
                               1933         [ +  - ]:            116 :                 if (*gmtoff != ttisp->tt_utoff ||
                               1934         [ -  + ]:            116 :                     *isdst != ttisp->tt_isdst)
                               1935                 :                :                 {
  555 tgl@sss.pgh.pa.us        1936                 :UBC           0 :                     *isfixed = false;
                               1937                 :              0 :                     break;      /* no point in looking further */
                               1938                 :                :                 }
                               1939                 :                :             }
                               1940                 :                :         }
                               1941                 :                :     }
                               1942                 :                : 
  555 tgl@sss.pgh.pa.us        1943                 :CBC         132 :     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
 7220                          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                 :                :     {
 2565                          2002         [ +  + ]:             74 :         if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
 7220                          2003                 :             56 :             return false;
                               2004                 :                :     }
 2565                          2005                 :            565 :     *gmtoff = sp->ttis[0].tt_utoff;
 7220                          2006                 :            565 :     return true;
                               2007                 :                : }
                               2008                 :                : 
                               2009                 :                : /*
                               2010                 :                :  * Return the name of the current timezone
                               2011                 :                :  */
                               2012                 :                : const char *
 7767 bruce@momjian.us         2013                 :          39595 : pg_get_timezone_name(pg_tz *tz)
                               2014                 :                : {
                               2015         [ +  - ]:          39595 :     if (tz)
                               2016                 :          39595 :         return tz->TZname;
 8100 tgl@sss.pgh.pa.us        2017                 :UBC           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
 5433 tgl@sss.pgh.pa.us        2028                 :CBC       23353 : 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                 :          23353 :     time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
                               2039                 :          23353 :     tt = pg_localtime(&time2000, tz);
                               2040   [ +  -  -  + ]:          23353 :     if (!tt || tt->tm_sec != 0)
 5433 tgl@sss.pgh.pa.us        2041                 :UBC           0 :         return false;
                               2042                 :                : 
 5433 tgl@sss.pgh.pa.us        2043                 :CBC       23353 :     return true;
                               2044                 :                : }
        

Generated by: LCOV version 2.0-1