LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-armor.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 89.2 % 231 206
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 10 10
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 72.6 % 168 122

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * pgp-armor.c
       3                 :             :  *      PGP ascii-armor.
       4                 :             :  *
       5                 :             :  * Copyright (c) 2005 Marko Kreen
       6                 :             :  * All rights reserved.
       7                 :             :  *
       8                 :             :  * Redistribution and use in source and binary forms, with or without
       9                 :             :  * modification, are permitted provided that the following conditions
      10                 :             :  * are met:
      11                 :             :  * 1. Redistributions of source code must retain the above copyright
      12                 :             :  *    notice, this list of conditions and the following disclaimer.
      13                 :             :  * 2. Redistributions in binary form must reproduce the above copyright
      14                 :             :  *    notice, this list of conditions and the following disclaimer in the
      15                 :             :  *    documentation and/or other materials provided with the distribution.
      16                 :             :  *
      17                 :             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      18                 :             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19                 :             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20                 :             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      21                 :             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22                 :             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23                 :             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24                 :             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25                 :             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26                 :             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27                 :             :  * SUCH DAMAGE.
      28                 :             :  *
      29                 :             :  * contrib/pgcrypto/pgp-armor.c
      30                 :             :  */
      31                 :             : 
      32                 :             : #include "postgres.h"
      33                 :             : 
      34                 :             : #include "pgp.h"
      35                 :             : #include "px.h"
      36                 :             : 
      37                 :             : /*
      38                 :             :  * BASE64 - duplicated :(
      39                 :             :  */
      40                 :             : 
      41                 :             : static const unsigned char _base64[] =
      42                 :             : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      43                 :             : 
      44                 :             : static int
      45                 :          10 : pg_base64_encode(const uint8 *src, unsigned len, uint8 *dst)
      46                 :             : {
      47                 :             :     uint8      *p,
      48                 :          10 :                *lend = dst + 76;
      49                 :             :     const uint8 *s,
      50                 :          10 :                *end = src + len;
      51                 :          10 :     int         pos = 2;
      52                 :          10 :     unsigned long buf = 0;
      53                 :             : 
      54                 :          10 :     s = src;
      55                 :          10 :     p = dst;
      56                 :             : 
      57         [ +  + ]:         131 :     while (s < end)
      58                 :             :     {
      59                 :         121 :         buf |= *s << (pos << 3);
      60                 :         121 :         pos--;
      61                 :         121 :         s++;
      62                 :             : 
      63                 :             :         /*
      64                 :             :          * write it out
      65                 :             :          */
      66         [ +  + ]:         121 :         if (pos < 0)
      67                 :             :         {
      68                 :          37 :             *p++ = _base64[(buf >> 18) & 0x3f];
      69                 :          37 :             *p++ = _base64[(buf >> 12) & 0x3f];
      70                 :          37 :             *p++ = _base64[(buf >> 6) & 0x3f];
      71                 :          37 :             *p++ = _base64[buf & 0x3f];
      72                 :             : 
      73                 :          37 :             pos = 2;
      74                 :          37 :             buf = 0;
      75                 :             :         }
      76         [ +  + ]:         121 :         if (p >= lend)
      77                 :             :         {
      78                 :           1 :             *p++ = '\n';
      79                 :           1 :             lend = p + 76;
      80                 :             :         }
      81                 :             :     }
      82         [ +  + ]:          10 :     if (pos != 2)
      83                 :             :     {
      84                 :           6 :         *p++ = _base64[(buf >> 18) & 0x3f];
      85                 :           6 :         *p++ = _base64[(buf >> 12) & 0x3f];
      86         [ +  + ]:           6 :         *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
      87                 :           6 :         *p++ = '=';
      88                 :             :     }
      89                 :             : 
      90                 :          10 :     return p - dst;
      91                 :             : }
      92                 :             : 
      93                 :             : /* probably should use lookup table */
      94                 :             : static int
      95                 :         180 : pg_base64_decode(const uint8 *src, unsigned len, uint8 *dst)
      96                 :             : {
      97                 :         180 :     const uint8 *srcend = src + len,
      98                 :         180 :                *s = src;
      99                 :         180 :     uint8      *p = dst;
     100                 :             :     char        c;
     101                 :         180 :     unsigned    b = 0;
     102                 :         180 :     unsigned long buf = 0;
     103                 :         180 :     int         pos = 0,
     104                 :         180 :                 end = 0;
     105                 :             : 
     106         [ +  + ]:       85230 :     while (s < srcend)
     107                 :             :     {
     108                 :       85050 :         c = *s++;
     109   [ +  +  +  + ]:       85050 :         if (c >= 'A' && c <= 'Z')
     110                 :       35677 :             b = c - 'A';
     111   [ +  +  +  - ]:       49373 :         else if (c >= 'a' && c <= 'z')
     112                 :       32798 :             b = c - 'a' + 26;
     113   [ +  +  +  + ]:       16575 :         else if (c >= '0' && c <= '9')
     114                 :       12478 :             b = c - '0' + 52;
     115         [ +  + ]:        4097 :         else if (c == '+')
     116                 :        1303 :             b = 62;
     117         [ +  + ]:        2794 :         else if (c == '/')
     118                 :        1344 :             b = 63;
     119         [ +  + ]:        1450 :         else if (c == '=')
     120                 :             :         {
     121                 :             :             /*
     122                 :             :              * end sequence
     123                 :             :              */
     124         [ +  + ]:         116 :             if (!end)
     125                 :             :             {
     126         [ +  + ]:          67 :                 if (pos == 2)
     127                 :          49 :                     end = 1;
     128         [ +  - ]:          18 :                 else if (pos == 3)
     129                 :          18 :                     end = 2;
     130                 :             :                 else
     131                 :           0 :                     return PXE_PGP_CORRUPT_ARMOR;
     132                 :             :             }
     133                 :         116 :             b = 0;
     134                 :             :         }
     135   [ +  +  +  -  :        1334 :         else if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
             -  +  -  - ]
     136                 :        1334 :             continue;
     137                 :             :         else
     138                 :           0 :             return PXE_PGP_CORRUPT_ARMOR;
     139                 :             : 
     140                 :             :         /*
     141                 :             :          * add it to buffer
     142                 :             :          */
     143                 :       83716 :         buf = (buf << 6) + b;
     144                 :       83716 :         pos++;
     145         [ +  + ]:       83716 :         if (pos == 4)
     146                 :             :         {
     147                 :       20929 :             *p++ = (buf >> 16) & 255;
     148   [ +  +  +  + ]:       20929 :             if (end == 0 || end > 1)
     149                 :       20880 :                 *p++ = (buf >> 8) & 255;
     150   [ +  +  -  + ]:       20929 :             if (end == 0 || end > 2)
     151                 :       20862 :                 *p++ = buf & 255;
     152                 :       20929 :             buf = 0;
     153                 :       20929 :             pos = 0;
     154                 :             :         }
     155                 :             :     }
     156                 :             : 
     157         [ -  + ]:         180 :     if (pos != 0)
     158                 :           0 :         return PXE_PGP_CORRUPT_ARMOR;
     159                 :         180 :     return p - dst;
     160                 :             : }
     161                 :             : 
     162                 :             : static unsigned
     163                 :          10 : pg_base64_enc_len(unsigned srclen)
     164                 :             : {
     165                 :             :     /*
     166                 :             :      * 3 bytes will be converted to 4, linefeed after 76 chars
     167                 :             :      */
     168                 :          10 :     return (srclen + 2) / 3 * 4 + srclen / (76 * 3 / 4);
     169                 :             : }
     170                 :             : 
     171                 :             : static unsigned
     172                 :          90 : pg_base64_dec_len(unsigned srclen)
     173                 :             : {
     174                 :          90 :     return (srclen * 3) >> 2;
     175                 :             : }
     176                 :             : 
     177                 :             : /*
     178                 :             :  * PGP armor
     179                 :             :  */
     180                 :             : 
     181                 :             : static const char *const armor_header = "-----BEGIN PGP MESSAGE-----\n";
     182                 :             : static const char *const armor_footer = "\n-----END PGP MESSAGE-----\n";
     183                 :             : 
     184                 :             : /* CRC24 implementation from rfc2440 */
     185                 :             : #define CRC24_INIT 0x00b704ceL
     186                 :             : #define CRC24_POLY 0x01864cfbL
     187                 :             : static long
     188                 :         100 : crc24(const uint8 *data, unsigned len)
     189                 :             : {
     190                 :         100 :     unsigned    crc = CRC24_INIT;
     191                 :             :     int         i;
     192                 :             : 
     193         [ +  + ]:       62622 :     while (len--)
     194                 :             :     {
     195                 :       62522 :         crc ^= (*data++) << 16;
     196         [ +  + ]:      562698 :         for (i = 0; i < 8; i++)
     197                 :             :         {
     198                 :      500176 :             crc <<= 1;
     199         [ +  + ]:      500176 :             if (crc & 0x1000000)
     200                 :      250518 :                 crc ^= CRC24_POLY;
     201                 :             :         }
     202                 :             :     }
     203                 :         100 :     return crc & 0xffffffL;
     204                 :             : }
     205                 :             : 
     206                 :             : void
     207                 :          10 : pgp_armor_encode(const uint8 *src, unsigned len, StringInfo dst,
     208                 :             :                  int num_headers, char **keys, char **values)
     209                 :             : {
     210                 :             :     int         n;
     211                 :             :     int         res;
     212                 :             :     unsigned    b64len;
     213                 :          10 :     unsigned    crc = crc24(src, len);
     214                 :             : 
     215                 :          10 :     appendStringInfoString(dst, armor_header);
     216                 :             : 
     217         [ +  + ]:          17 :     for (n = 0; n < num_headers; n++)
     218                 :           7 :         appendStringInfo(dst, "%s: %s\n", keys[n], values[n]);
     219                 :          10 :     appendStringInfoChar(dst, '\n');
     220                 :             : 
     221                 :             :     /* make sure we have enough room to pg_base64_encode() */
     222                 :          10 :     b64len = pg_base64_enc_len(len);
     223                 :          10 :     enlargeStringInfo(dst, (int) b64len);
     224                 :             : 
     225                 :          10 :     res = pg_base64_encode(src, len, (uint8 *) dst->data + dst->len);
     226         [ -  + ]:          10 :     if (res > b64len)
     227         [ #  # ]:           0 :         elog(FATAL, "overflow - encode estimate too small");
     228                 :          10 :     dst->len += res;
     229                 :             : 
     230         [ +  + ]:          10 :     if (*(dst->data + dst->len - 1) != '\n')
     231                 :           6 :         appendStringInfoChar(dst, '\n');
     232                 :             : 
     233                 :          10 :     appendStringInfoChar(dst, '=');
     234                 :          10 :     appendStringInfoChar(dst, _base64[(crc >> 18) & 0x3f]);
     235                 :          10 :     appendStringInfoChar(dst, _base64[(crc >> 12) & 0x3f]);
     236                 :          10 :     appendStringInfoChar(dst, _base64[(crc >> 6) & 0x3f]);
     237                 :          10 :     appendStringInfoChar(dst, _base64[crc & 0x3f]);
     238                 :             : 
     239                 :          10 :     appendStringInfoString(dst, armor_footer);
     240                 :          10 : }
     241                 :             : 
     242                 :             : static const uint8 *
     243                 :         209 : find_str(const uint8 *data, const uint8 *data_end, const char *str, int strlen)
     244                 :             : {
     245                 :         209 :     const uint8 *p = data;
     246                 :             : 
     247         [ -  + ]:         209 :     if (!strlen)
     248                 :           0 :         return NULL;
     249         [ -  + ]:         209 :     if (data_end - data < strlen)
     250                 :           0 :         return NULL;
     251         [ +  - ]:         224 :     while (p < data_end)
     252                 :             :     {
     253                 :         224 :         p = memchr(p, str[0], data_end - p);
     254         [ -  + ]:         224 :         if (p == NULL)
     255                 :           0 :             return NULL;
     256         [ -  + ]:         224 :         if (p + strlen > data_end)
     257                 :           0 :             return NULL;
     258         [ +  + ]:         224 :         if (memcmp(p, str, strlen) == 0)
     259                 :         209 :             return p;
     260                 :          15 :         p++;
     261                 :             :     }
     262                 :           0 :     return NULL;
     263                 :             : }
     264                 :             : 
     265                 :             : static int
     266                 :         208 : find_header(const uint8 *data, const uint8 *datend,
     267                 :             :             const uint8 **start_p, int is_end)
     268                 :             : {
     269                 :         208 :     const uint8 *p = data;
     270                 :             :     static const char *start_sep = "-----BEGIN";
     271                 :             :     static const char *end_sep = "-----END";
     272         [ +  + ]:         208 :     const char *sep = is_end ? end_sep : start_sep;
     273                 :             : 
     274                 :             :     /* find header line */
     275                 :             :     while (1)
     276                 :             :     {
     277                 :         209 :         p = find_str(p, datend, sep, strlen(sep));
     278         [ -  + ]:         209 :         if (p == NULL)
     279                 :           0 :             return PXE_PGP_CORRUPT_ARMOR;
     280                 :             :         /* it must start at beginning of line */
     281   [ +  +  +  + ]:         209 :         if (p == data || *(p - 1) == '\n')
     282                 :             :             break;
     283                 :           1 :         p += strlen(sep);
     284                 :             :     }
     285                 :         208 :     *start_p = p;
     286                 :         208 :     p += strlen(sep);
     287                 :             : 
     288                 :             :     /* check if header text ok */
     289   [ +  -  +  + ]:        3438 :     for (; p < datend && *p != '-'; p++)
     290                 :             :     {
     291                 :             :         /* various junk can be there, but definitely not line-feed  */
     292         [ +  - ]:        3230 :         if (*p >= ' ')
     293                 :        3230 :             continue;
     294                 :           0 :         return PXE_PGP_CORRUPT_ARMOR;
     295                 :             :     }
     296   [ +  -  -  + ]:         208 :     if (datend - p < 5 || memcmp(p, sep, 5) != 0)
     297                 :           0 :         return PXE_PGP_CORRUPT_ARMOR;
     298                 :         208 :     p += 5;
     299                 :             : 
     300                 :             :     /* check if at end of line */
     301         [ +  + ]:         208 :     if (p < datend)
     302                 :             :     {
     303   [ +  +  -  + ]:         207 :         if (*p != '\n' && *p != '\r')
     304                 :           0 :             return PXE_PGP_CORRUPT_ARMOR;
     305         [ +  + ]:         207 :         if (*p == '\r')
     306                 :           2 :             p++;
     307   [ +  -  +  - ]:         207 :         if (p < datend && *p == '\n')
     308                 :         207 :             p++;
     309                 :             :     }
     310                 :         208 :     return p - *start_p;
     311                 :             : }
     312                 :             : 
     313                 :             : int
     314                 :          90 : pgp_armor_decode(const uint8 *src, int len, StringInfo dst)
     315                 :             : {
     316                 :          90 :     const uint8 *p = src;
     317                 :          90 :     const uint8 *data_end = src + len;
     318                 :             :     long        crc;
     319                 :             :     const uint8 *base64_start,
     320                 :             :                *armor_end;
     321                 :          90 :     const uint8 *base64_end = NULL;
     322                 :             :     uint8       buf[4];
     323                 :             :     int         hlen;
     324                 :             :     int         blen;
     325                 :          90 :     int         res = PXE_PGP_CORRUPT_ARMOR;
     326                 :             : 
     327                 :             :     /* armor start */
     328                 :          90 :     hlen = find_header(src, data_end, &p, 0);
     329         [ -  + ]:          90 :     if (hlen <= 0)
     330                 :           0 :         goto out;
     331                 :          90 :     p += hlen;
     332                 :             : 
     333                 :             :     /* armor end */
     334                 :          90 :     hlen = find_header(p, data_end, &armor_end, 1);
     335         [ -  + ]:          90 :     if (hlen <= 0)
     336                 :           0 :         goto out;
     337                 :             : 
     338                 :             :     /* skip comments - find empty line */
     339   [ +  -  +  +  :         169 :     while (p < armor_end && *p != '\n' && *p != '\r')
                   +  - ]
     340                 :             :     {
     341                 :          79 :         p = memchr(p, '\n', armor_end - p);
     342         [ -  + ]:          79 :         if (!p)
     343                 :           0 :             goto out;
     344                 :             : 
     345                 :             :         /* step to start of next line */
     346                 :          79 :         p++;
     347                 :             :     }
     348                 :          90 :     base64_start = p;
     349                 :             : 
     350                 :             :     /* find crc pos */
     351         [ +  - ]:         631 :     for (p = armor_end; p >= base64_start; p--)
     352         [ +  + ]:         631 :         if (*p == '=')
     353                 :             :         {
     354                 :          90 :             base64_end = p - 1;
     355                 :          90 :             break;
     356                 :             :         }
     357         [ -  + ]:          90 :     if (base64_end == NULL)
     358                 :           0 :         goto out;
     359                 :             : 
     360                 :             :     /* decode crc */
     361         [ -  + ]:          90 :     if (pg_base64_decode(p + 1, 4, buf) != 3)
     362                 :           0 :         goto out;
     363                 :          90 :     crc = (((long) buf[0]) << 16) + (((long) buf[1]) << 8) + (long) buf[2];
     364                 :             : 
     365                 :             :     /* decode data */
     366                 :          90 :     blen = (int) pg_base64_dec_len(len);
     367                 :          90 :     enlargeStringInfo(dst, blen);
     368                 :          90 :     res = pg_base64_decode(base64_start, base64_end - base64_start, (uint8 *) dst->data);
     369         [ -  + ]:          90 :     if (res > blen)
     370         [ #  # ]:           0 :         elog(FATAL, "overflow - decode estimate too small");
     371         [ -  + ]:          90 :     if (res >= 0)
     372                 :             :     {
     373         [ +  + ]:          90 :         if (crc24((uint8 *) dst->data, res) == crc)
     374                 :          89 :             dst->len += res;
     375                 :             :         else
     376                 :           1 :             res = PXE_PGP_CORRUPT_ARMOR;
     377                 :             :     }
     378                 :           0 : out:
     379                 :          90 :     return res;
     380                 :             : }
     381                 :             : 
     382                 :             : /*
     383                 :             :  * Extracts all armor headers from an ASCII-armored input.
     384                 :             :  *
     385                 :             :  * Returns 0 on success, or PXE_* error code on error. On success, the
     386                 :             :  * number of headers and their keys and values are returned in *nheaders,
     387                 :             :  * *nkeys and *nvalues.
     388                 :             :  */
     389                 :             : int
     390                 :          14 : pgp_extract_armor_headers(const uint8 *src, unsigned len,
     391                 :             :                           int *nheaders, char ***keys, char ***values)
     392                 :             : {
     393                 :          14 :     const uint8 *data_end = src + len;
     394                 :             :     const uint8 *p;
     395                 :             :     const uint8 *base64_start;
     396                 :             :     const uint8 *armor_start;
     397                 :             :     const uint8 *armor_end;
     398                 :             :     Size        armor_len;
     399                 :             :     char       *line;
     400                 :             :     char       *nextline;
     401                 :             :     char       *eol,
     402                 :             :                *colon;
     403                 :             :     int         hlen;
     404                 :             :     char       *buf;
     405                 :             :     int         hdrlines;
     406                 :             :     int         n;
     407                 :             : 
     408                 :             :     /* armor start */
     409                 :          14 :     hlen = find_header(src, data_end, &armor_start, 0);
     410         [ -  + ]:          14 :     if (hlen <= 0)
     411                 :           0 :         return PXE_PGP_CORRUPT_ARMOR;
     412                 :          14 :     armor_start += hlen;
     413                 :             : 
     414                 :             :     /* armor end */
     415                 :          14 :     hlen = find_header(armor_start, data_end, &armor_end, 1);
     416         [ -  + ]:          14 :     if (hlen <= 0)
     417                 :           0 :         return PXE_PGP_CORRUPT_ARMOR;
     418                 :             : 
     419                 :             :     /* Count the number of armor header lines. */
     420                 :          14 :     hdrlines = 0;
     421                 :          14 :     p = armor_start;
     422   [ +  +  +  +  :          40 :     while (p < armor_end && *p != '\n' && *p != '\r')
                   +  + ]
     423                 :             :     {
     424                 :          26 :         p = memchr(p, '\n', armor_end - p);
     425         [ -  + ]:          26 :         if (!p)
     426                 :           0 :             return PXE_PGP_CORRUPT_ARMOR;
     427                 :             : 
     428                 :             :         /* step to start of next line */
     429                 :          26 :         p++;
     430                 :          26 :         hdrlines++;
     431                 :             :     }
     432                 :          14 :     base64_start = p;
     433                 :             : 
     434                 :             :     /*
     435                 :             :      * Make a modifiable copy of the part of the input that contains the
     436                 :             :      * headers. The returned key/value pointers will point inside the buffer.
     437                 :             :      */
     438                 :          14 :     armor_len = base64_start - armor_start;
     439                 :          14 :     buf = palloc(armor_len + 1);
     440                 :          14 :     memcpy(buf, armor_start, armor_len);
     441                 :          14 :     buf[armor_len] = '\0';
     442                 :             : 
     443                 :             :     /* Allocate return arrays */
     444                 :          14 :     *keys = (char **) palloc(hdrlines * sizeof(char *));
     445                 :          14 :     *values = (char **) palloc(hdrlines * sizeof(char *));
     446                 :             : 
     447                 :             :     /*
     448                 :             :      * Split the header lines at newlines and ": " separators, and collect
     449                 :             :      * pointers to the keys and values in the return arrays.
     450                 :             :      */
     451                 :          14 :     n = 0;
     452                 :          14 :     line = buf;
     453                 :             :     for (;;)
     454                 :             :     {
     455                 :             :         /* find end of line */
     456                 :          60 :         eol = strchr(line, '\n');
     457         [ +  + ]:          37 :         if (!eol)
     458                 :          12 :             break;
     459                 :          25 :         nextline = eol + 1;
     460                 :             :         /* if the line ends in CR + LF, strip the CR */
     461   [ +  -  +  + ]:          25 :         if (eol > line && *(eol - 1) == '\r')
     462                 :           2 :             eol--;
     463                 :          25 :         *eol = '\0';
     464                 :             : 
     465                 :             :         /* find colon+space separating the key and value */
     466                 :          25 :         colon = strstr(line, ": ");
     467         [ +  + ]:          25 :         if (!colon)
     468                 :           2 :             return PXE_PGP_CORRUPT_ARMOR;
     469                 :          23 :         *colon = '\0';
     470                 :             : 
     471                 :             :         /* shouldn't happen, we counted the number of lines beforehand */
     472         [ -  + ]:          23 :         if (n >= hdrlines)
     473         [ #  # ]:           0 :             elog(ERROR, "unexpected number of armor header lines");
     474                 :             : 
     475                 :          23 :         (*keys)[n] = line;
     476                 :          23 :         (*values)[n] = colon + 2;
     477                 :          23 :         n++;
     478                 :             : 
     479                 :             :         /* step to start of next line */
     480                 :          23 :         line = nextline;
     481                 :             :     }
     482                 :             : 
     483         [ -  + ]:          12 :     if (n != hdrlines)
     484         [ #  # ]:           0 :         elog(ERROR, "unexpected number of armor header lines");
     485                 :             : 
     486                 :          12 :     *nheaders = n;
     487                 :          12 :     return 0;
     488                 :             : }
        

Generated by: LCOV version 2.0-1