LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - encode.c (source / functions) Coverage Total Hit UNC LBC UIC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 88.8 % 223 198 1 17 7 4 112 10 72 21 104 5
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 17 17 15 2 17
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * encode.c
       4                 :  *    Various data encoding/decoding things.
       5                 :  *
       6                 :  * Copyright (c) 2001-2023, PostgreSQL Global Development Group
       7                 :  *
       8                 :  *
       9                 :  * IDENTIFICATION
      10                 :  *    src/backend/utils/adt/encode.c
      11                 :  *
      12                 :  *-------------------------------------------------------------------------
      13                 :  */
      14                 : #include "postgres.h"
      15                 : 
      16                 : #include <ctype.h>
      17                 : 
      18                 : #include "mb/pg_wchar.h"
      19                 : #include "utils/builtins.h"
      20                 : #include "utils/memutils.h"
      21                 : #include "varatt.h"
      22                 : 
      23                 : 
      24                 : /*
      25                 :  * Encoding conversion API.
      26                 :  * encode_len() and decode_len() compute the amount of space needed, while
      27                 :  * encode() and decode() perform the actual conversions.  It is okay for
      28                 :  * the _len functions to return an overestimate, but not an underestimate.
      29                 :  * (Having said that, large overestimates could cause unnecessary errors,
      30                 :  * so it's better to get it right.)  The conversion routines write to the
      31                 :  * buffer at *res and return the true length of their output.
      32                 :  */
      33                 : struct pg_encoding
      34                 : {
      35                 :     uint64      (*encode_len) (const char *data, size_t dlen);
      36                 :     uint64      (*decode_len) (const char *data, size_t dlen);
      37                 :     uint64      (*encode) (const char *data, size_t dlen, char *res);
      38                 :     uint64      (*decode) (const char *data, size_t dlen, char *res);
      39                 : };
      40                 : 
      41                 : static const struct pg_encoding *pg_find_encoding(const char *name);
      42                 : 
      43                 : /*
      44                 :  * SQL functions.
      45                 :  */
      46                 : 
      47                 : Datum
      48 GIC       99209 : binary_encode(PG_FUNCTION_ARGS)
      49 ECB             : {
      50 GIC       99209 :     bytea      *data = PG_GETARG_BYTEA_PP(0);
      51 CBC       99209 :     Datum       name = PG_GETARG_DATUM(1);
      52 ECB             :     text       *result;
      53                 :     char       *namebuf;
      54                 :     char       *dataptr;
      55                 :     size_t      datalen;
      56                 :     uint64      resultlen;
      57                 :     uint64      res;
      58                 :     const struct pg_encoding *enc;
      59                 : 
      60 GIC       99209 :     namebuf = TextDatumGetCString(name);
      61 ECB             : 
      62 GIC       99209 :     enc = pg_find_encoding(namebuf);
      63 CBC       99209 :     if (enc == NULL)
      64 LBC           0 :         ereport(ERROR,
      65 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      66                 :                  errmsg("unrecognized encoding: \"%s\"", namebuf)));
      67                 : 
      68 GIC       99209 :     dataptr = VARDATA_ANY(data);
      69 CBC       99209 :     datalen = VARSIZE_ANY_EXHDR(data);
      70 ECB             : 
      71 GIC       99209 :     resultlen = enc->encode_len(dataptr, datalen);
      72 ECB             : 
      73                 :     /*
      74                 :      * resultlen possibly overflows uint32, therefore on 32-bit machines it's
      75                 :      * unsafe to rely on palloc's internal check.
      76                 :      */
      77 GIC       99209 :     if (resultlen > MaxAllocSize - VARHDRSZ)
      78 LBC           0 :         ereport(ERROR,
      79 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
      80                 :                  errmsg("result of encoding conversion is too large")));
      81                 : 
      82 GIC       99209 :     result = palloc(VARHDRSZ + resultlen);
      83 ECB             : 
      84 GIC       99209 :     res = enc->encode(dataptr, datalen, VARDATA(result));
      85 ECB             : 
      86                 :     /* Make this FATAL 'cause we've trodden on memory ... */
      87 GIC       99209 :     if (res > resultlen)
      88 LBC           0 :         elog(FATAL, "overflow - encode estimate too small");
      89 EUB             : 
      90 GIC       99209 :     SET_VARSIZE(result, VARHDRSZ + res);
      91 ECB             : 
      92 GIC       99209 :     PG_RETURN_TEXT_P(result);
      93 ECB             : }
      94                 : 
      95                 : Datum
      96 GIC       16426 : binary_decode(PG_FUNCTION_ARGS)
      97 ECB             : {
      98 GIC       16426 :     text       *data = PG_GETARG_TEXT_PP(0);
      99 CBC       16426 :     Datum       name = PG_GETARG_DATUM(1);
     100 ECB             :     bytea      *result;
     101                 :     char       *namebuf;
     102                 :     char       *dataptr;
     103                 :     size_t      datalen;
     104                 :     uint64      resultlen;
     105                 :     uint64      res;
     106                 :     const struct pg_encoding *enc;
     107                 : 
     108 GIC       16426 :     namebuf = TextDatumGetCString(name);
     109 ECB             : 
     110 GIC       16426 :     enc = pg_find_encoding(namebuf);
     111 CBC       16426 :     if (enc == NULL)
     112 LBC           0 :         ereport(ERROR,
     113 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     114                 :                  errmsg("unrecognized encoding: \"%s\"", namebuf)));
     115                 : 
     116 GIC       16426 :     dataptr = VARDATA_ANY(data);
     117 CBC       16426 :     datalen = VARSIZE_ANY_EXHDR(data);
     118 ECB             : 
     119 GIC       16426 :     resultlen = enc->decode_len(dataptr, datalen);
     120 ECB             : 
     121                 :     /*
     122                 :      * resultlen possibly overflows uint32, therefore on 32-bit machines it's
     123                 :      * unsafe to rely on palloc's internal check.
     124                 :      */
     125 GIC       16426 :     if (resultlen > MaxAllocSize - VARHDRSZ)
     126 LBC           0 :         ereport(ERROR,
     127 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     128                 :                  errmsg("result of decoding conversion is too large")));
     129                 : 
     130 GIC       16426 :     result = palloc(VARHDRSZ + resultlen);
     131 ECB             : 
     132 GIC       16426 :     res = enc->decode(dataptr, datalen, VARDATA(result));
     133 ECB             : 
     134                 :     /* Make this FATAL 'cause we've trodden on memory ... */
     135 GIC       16426 :     if (res > resultlen)
     136 LBC           0 :         elog(FATAL, "overflow - decode estimate too small");
     137 EUB             : 
     138 GIC       16426 :     SET_VARSIZE(result, VARHDRSZ + res);
     139 ECB             : 
     140 GIC       16426 :     PG_RETURN_BYTEA_P(result);
     141 ECB             : }
     142                 : 
     143                 : 
     144                 : /*
     145                 :  * HEX
     146                 :  */
     147                 : 
     148                 : static const char hextbl[] = "0123456789abcdef";
     149                 : 
     150                 : static const int8 hexlookup[128] = {
     151                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     152                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     153                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     154                 :     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
     155                 :     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     156                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     157                 :     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     158                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     159                 : };
     160                 : 
     161                 : uint64
     162 GIC      224346 : hex_encode(const char *src, size_t len, char *dst)
     163 ECB             : {
     164 GIC      224346 :     const char *end = src + len;
     165 ECB             : 
     166 GIC     4117982 :     while (src < end)
     167 ECB             :     {
     168 GIC     3893636 :         *dst++ = hextbl[(*src >> 4) & 0xF];
     169 CBC     3893636 :         *dst++ = hextbl[*src & 0xF];
     170         3893636 :         src++;
     171 ECB             :     }
     172 GIC      224346 :     return (uint64) len * 2;
     173 ECB             : }
     174                 : 
     175                 : static inline bool
     176 GNC      432945 : get_hex(const char *cp, char *out)
     177 ECB             : {
     178 GIC      432945 :     unsigned char c = (unsigned char) *cp;
     179 CBC      432945 :     int         res = -1;
     180 ECB             : 
     181 GIC      432945 :     if (c < 127)
     182 CBC      432945 :         res = hexlookup[c];
     183 ECB             : 
     184 GNC      432945 :     *out = (char) res;
     185                 : 
     186          432945 :     return (res >= 0);
     187 ECB             : }
     188                 : 
     189                 : uint64
     190 GIC       16406 : hex_decode(const char *src, size_t len, char *dst)
     191                 : {
     192 GNC       16406 :     return hex_decode_safe(src, len, dst, NULL);
     193                 : }
     194                 : 
     195                 : uint64
     196           16811 : hex_decode_safe(const char *src, size_t len, char *dst, Node *escontext)
     197                 : {
     198                 :     const char *s,
     199 ECB             :                *srcend;
     200                 :     char        v1,
     201                 :                 v2,
     202                 :                *p;
     203                 : 
     204 GIC       16811 :     srcend = src + len;
     205           16811 :     s = src;
     206           16811 :     p = dst;
     207 CBC      233303 :     while (s < srcend)
     208 ECB             :     {
     209 CBC      216507 :         if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
     210 ECB             :         {
     211 GIC          30 :             s++;
     212 CBC          30 :             continue;
     213                 :         }
     214 GNC      216477 :         if (!get_hex(s, &v1))
     215 UNC           0 :             ereturn(escontext, 0,
     216                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     217                 :                      errmsg("invalid hexadecimal digit: \"%.*s\"",
     218                 :                             pg_mblen(s), s)));
     219 CBC      216477 :         s++;
     220 GIC      216477 :         if (s >= srcend)
     221 GNC           9 :             ereturn(escontext, 0,
     222 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     223                 :                      errmsg("invalid hexadecimal data: odd number of digits")));
     224 GNC      216468 :         if (!get_hex(s, &v2))
     225               6 :             ereturn(escontext, 0,
     226                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     227                 :                      errmsg("invalid hexadecimal digit: \"%.*s\"",
     228                 :                             pg_mblen(s), s)));
     229 CBC      216462 :         s++;
     230 GNC      216462 :         *p++ = (v1 << 4) | v2;
     231 ECB             :     }
     232                 : 
     233 GIC       16796 :     return p - dst;
     234 ECB             : }
     235                 : 
     236                 : static uint64
     237 GIC       99174 : hex_enc_len(const char *src, size_t srclen)
     238                 : {
     239 CBC       99174 :     return (uint64) srclen << 1;
     240 ECB             : }
     241                 : 
     242                 : static uint64
     243 CBC       16406 : hex_dec_len(const char *src, size_t srclen)
     244                 : {
     245 GIC       16406 :     return (uint64) srclen >> 1;
     246                 : }
     247 ECB             : 
     248                 : /*
     249                 :  * BASE64
     250                 :  */
     251                 : 
     252                 : static const char _base64[] =
     253                 : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     254                 : 
     255                 : static const int8 b64lookup[128] = {
     256                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     257                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     258                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
     259                 :     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
     260                 :     -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
     261                 :     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
     262                 :     -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
     263                 :     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
     264                 : };
     265                 : 
     266                 : static uint64
     267 GIC           6 : pg_base64_encode(const char *src, size_t len, char *dst)
     268                 : {
     269                 :     char       *p,
     270               6 :                *lend = dst + 76;
     271                 :     const char *s,
     272               6 :                *end = src + len;
     273               6 :     int         pos = 2;
     274               6 :     uint32      buf = 0;
     275                 : 
     276               6 :     s = src;
     277 CBC           6 :     p = dst;
     278                 : 
     279 GIC         426 :     while (s < end)
     280 ECB             :     {
     281 GIC         420 :         buf |= (unsigned char) *s << (pos << 3);
     282 CBC         420 :         pos--;
     283             420 :         s++;
     284 ECB             : 
     285                 :         /* write it out */
     286 CBC         420 :         if (pos < 0)
     287 ECB             :         {
     288 GIC         138 :             *p++ = _base64[(buf >> 18) & 0x3f];
     289 CBC         138 :             *p++ = _base64[(buf >> 12) & 0x3f];
     290 GIC         138 :             *p++ = _base64[(buf >> 6) & 0x3f];
     291 CBC         138 :             *p++ = _base64[buf & 0x3f];
     292 ECB             : 
     293 CBC         138 :             pos = 2;
     294 GIC         138 :             buf = 0;
     295                 :         }
     296 CBC         420 :         if (p >= lend)
     297                 :         {
     298               6 :             *p++ = '\n';
     299               6 :             lend = p + 76;
     300 ECB             :         }
     301                 :     }
     302 GIC           6 :     if (pos != 2)
     303 ECB             :     {
     304 CBC           6 :         *p++ = _base64[(buf >> 18) & 0x3f];
     305 GIC           6 :         *p++ = _base64[(buf >> 12) & 0x3f];
     306 CBC           6 :         *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
     307 GIC           6 :         *p++ = '=';
     308 ECB             :     }
     309                 : 
     310 GIC           6 :     return p - dst;
     311                 : }
     312 ECB             : 
     313                 : static uint64
     314 CBC           5 : pg_base64_decode(const char *src, size_t len, char *dst)
     315 ECB             : {
     316 CBC           5 :     const char *srcend = src + len,
     317               5 :                *s = src;
     318 GIC           5 :     char       *p = dst;
     319                 :     char        c;
     320 CBC           5 :     int         b = 0;
     321 GIC           5 :     uint32      buf = 0;
     322               5 :     int         pos = 0,
     323               5 :                 end = 0;
     324 ECB             : 
     325 GIC         312 :     while (s < srcend)
     326 ECB             :     {
     327 CBC         307 :         c = *s++;
     328 ECB             : 
     329 GIC         307 :         if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
     330 CBC           3 :             continue;
     331 ECB             : 
     332 CBC         304 :         if (c == '=')
     333 ECB             :         {
     334                 :             /* end sequence */
     335 CBC           8 :             if (!end)
     336                 :             {
     337               5 :                 if (pos == 2)
     338 GIC           3 :                     end = 1;
     339 CBC           2 :                 else if (pos == 3)
     340               2 :                     end = 2;
     341                 :                 else
     342 LBC           0 :                     ereport(ERROR,
     343                 :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     344                 :                              errmsg("unexpected \"=\" while decoding base64 sequence")));
     345 ECB             :             }
     346 GIC           8 :             b = 0;
     347 ECB             :         }
     348                 :         else
     349                 :         {
     350 CBC         296 :             b = -1;
     351 GIC         296 :             if (c > 0 && c < 127)
     352 GBC         296 :                 b = b64lookup[(unsigned char) c];
     353 GIC         296 :             if (b < 0)
     354 UIC           0 :                 ereport(ERROR,
     355                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     356 ECB             :                          errmsg("invalid symbol \"%.*s\" found while decoding base64 sequence",
     357                 :                                 pg_mblen(s - 1), s - 1)));
     358                 :         }
     359                 :         /* add it to buffer */
     360 CBC         304 :         buf = (buf << 6) + b;
     361             304 :         pos++;
     362             304 :         if (pos == 4)
     363 ECB             :         {
     364 GBC          76 :             *p++ = (buf >> 16) & 255;
     365 GIC          76 :             if (end == 0 || end > 1)
     366              73 :                 *p++ = (buf >> 8) & 255;
     367              76 :             if (end == 0 || end > 2)
     368              71 :                 *p++ = buf & 255;
     369              76 :             buf = 0;
     370 CBC          76 :             pos = 0;
     371 ECB             :         }
     372                 :     }
     373                 : 
     374 CBC           5 :     if (pos != 0)
     375 LBC           0 :         ereport(ERROR,
     376 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     377                 :                  errmsg("invalid base64 end sequence"),
     378                 :                  errhint("Input data is missing padding, is truncated, or is otherwise corrupted.")));
     379                 : 
     380 CBC           5 :     return p - dst;
     381                 : }
     382                 : 
     383                 : 
     384 ECB             : static uint64
     385 GBC           6 : pg_base64_enc_len(const char *src, size_t srclen)
     386                 : {
     387                 :     /* 3 bytes will be converted to 4, linefeed after 76 chars */
     388 GIC           6 :     return ((uint64) srclen + 2) * 4 / 3 + (uint64) srclen / (76 * 3 / 4);
     389                 : }
     390 ECB             : 
     391                 : static uint64
     392 GIC           5 : pg_base64_dec_len(const char *src, size_t srclen)
     393                 : {
     394               5 :     return ((uint64) srclen * 3) >> 2;
     395 ECB             : }
     396                 : 
     397                 : /*
     398                 :  * Escape
     399                 :  * Minimally escape bytea to text.
     400                 :  * De-escape text to bytea.
     401                 :  *
     402                 :  * We must escape zero bytes and high-bit-set bytes to avoid generating
     403                 :  * text that might be invalid in the current encoding, or that might
     404                 :  * change to something else if passed through an encoding conversion
     405                 :  * (leading to failing to de-escape to the original bytea value).
     406                 :  * Also of course backslash itself has to be escaped.
     407                 :  *
     408                 :  * De-escaping processes \\ and any \### octal
     409                 :  */
     410                 : 
     411                 : #define VAL(CH)         ((CH) - '0')
     412                 : #define DIG(VAL)        ((VAL) + '0')
     413                 : 
     414                 : static uint64
     415 GIC          29 : esc_encode(const char *src, size_t srclen, char *dst)
     416                 : {
     417              29 :     const char *end = src + srclen;
     418              29 :     char       *rp = dst;
     419              29 :     uint64      len = 0;
     420                 : 
     421             261 :     while (src < end)
     422                 :     {
     423             232 :         unsigned char c = (unsigned char) *src;
     424                 : 
     425 CBC         232 :         if (c == '\0' || IS_HIGHBIT_SET(c))
     426                 :         {
     427              42 :             rp[0] = '\\';
     428              42 :             rp[1] = DIG(c >> 6);
     429              42 :             rp[2] = DIG((c >> 3) & 7);
     430 GIC          42 :             rp[3] = DIG(c & 7);
     431 CBC          42 :             rp += 4;
     432 GIC          42 :             len += 4;
     433 ECB             :         }
     434 GIC         190 :         else if (c == '\\')
     435 ECB             :         {
     436 UIC           0 :             rp[0] = '\\';
     437 LBC           0 :             rp[1] = '\\';
     438               0 :             rp += 2;
     439               0 :             len += 2;
     440 ECB             :         }
     441                 :         else
     442                 :         {
     443 GIC         190 :             *rp++ = c;
     444 CBC         190 :             len++;
     445                 :         }
     446 EUB             : 
     447 GBC         232 :         src++;
     448 EUB             :     }
     449                 : 
     450 GIC          29 :     return len;
     451                 : }
     452                 : 
     453 ECB             : static uint64
     454 CBC          15 : esc_decode(const char *src, size_t srclen, char *dst)
     455                 : {
     456 GIC          15 :     const char *end = src + srclen;
     457 CBC          15 :     char       *rp = dst;
     458 GIC          15 :     uint64      len = 0;
     459                 : 
     460 CBC     1200042 :     while (src < end)
     461                 :     {
     462 GIC     1200027 :         if (src[0] != '\\')
     463         1200012 :             *rp++ = *src++;
     464 CBC          15 :         else if (src + 3 < end &&
     465 GIC          15 :                  (src[1] >= '0' && src[1] <= '3') &&
     466 CBC          15 :                  (src[2] >= '0' && src[2] <= '7') &&
     467              15 :                  (src[3] >= '0' && src[3] <= '7'))
     468              15 :         {
     469                 :             int         val;
     470 ECB             : 
     471 GIC          15 :             val = VAL(src[1]);
     472 CBC          15 :             val <<= 3;
     473              15 :             val += VAL(src[2]);
     474              15 :             val <<= 3;
     475              15 :             *rp++ = val + VAL(src[3]);
     476              15 :             src += 4;
     477 ECB             :         }
     478 LBC           0 :         else if (src + 1 < end &&
     479 UIC           0 :                  (src[1] == '\\'))
     480                 :         {
     481 LBC           0 :             *rp++ = '\\';
     482               0 :             src += 2;
     483 ECB             :         }
     484                 :         else
     485                 :         {
     486                 :             /*
     487                 :              * One backslash, not followed by ### valid octal. Should never
     488 EUB             :              * get here, since esc_dec_len does same check.
     489                 :              */
     490 UIC           0 :             ereport(ERROR,
     491 EUB             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     492                 :                      errmsg("invalid input syntax for type %s", "bytea")));
     493                 :         }
     494                 : 
     495 GIC     1200027 :         len++;
     496                 :     }
     497                 : 
     498              15 :     return len;
     499                 : }
     500 EUB             : 
     501                 : static uint64
     502 GIC          29 : esc_enc_len(const char *src, size_t srclen)
     503                 : {
     504              29 :     const char *end = src + srclen;
     505 CBC          29 :     uint64      len = 0;
     506                 : 
     507 GIC         261 :     while (src < end)
     508 ECB             :     {
     509 GIC         232 :         if (*src == '\0' || IS_HIGHBIT_SET(*src))
     510              42 :             len += 4;
     511             190 :         else if (*src == '\\')
     512 LBC           0 :             len += 2;
     513                 :         else
     514 CBC         190 :             len++;
     515 ECB             : 
     516 GIC         232 :         src++;
     517 ECB             :     }
     518                 : 
     519 CBC          29 :     return len;
     520 ECB             : }
     521                 : 
     522 EUB             : static uint64
     523 GIC          15 : esc_dec_len(const char *src, size_t srclen)
     524 ECB             : {
     525 GIC          15 :     const char *end = src + srclen;
     526 CBC          15 :     uint64      len = 0;
     527                 : 
     528 GIC     1200042 :     while (src < end)
     529 ECB             :     {
     530 GIC     1200027 :         if (src[0] != '\\')
     531         1200012 :             src++;
     532              15 :         else if (src + 3 < end &&
     533 CBC          15 :                  (src[1] >= '0' && src[1] <= '3') &&
     534 GIC          15 :                  (src[2] >= '0' && src[2] <= '7') &&
     535 CBC          15 :                  (src[3] >= '0' && src[3] <= '7'))
     536 ECB             :         {
     537                 :             /*
     538                 :              * backslash + valid octal
     539                 :              */
     540 CBC          15 :             src += 4;
     541 ECB             :         }
     542 LBC           0 :         else if (src + 1 < end &&
     543               0 :                  (src[1] == '\\'))
     544 ECB             :         {
     545                 :             /*
     546                 :              * two backslashes = backslash
     547                 :              */
     548 UIC           0 :             src += 2;
     549                 :         }
     550 ECB             :         else
     551                 :         {
     552 EUB             :             /*
     553                 :              * one backslash, not followed by ### valid octal
     554                 :              */
     555 UIC           0 :             ereport(ERROR,
     556                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     557                 :                      errmsg("invalid input syntax for type %s", "bytea")));
     558 EUB             :         }
     559                 : 
     560 GIC     1200027 :         len++;
     561                 :     }
     562              15 :     return len;
     563                 : }
     564                 : 
     565 EUB             : /*
     566                 :  * Common
     567                 :  */
     568                 : 
     569                 : static const struct
     570 ECB             : {
     571                 :     const char *name;
     572                 :     struct pg_encoding enc;
     573                 : }           enclist[] =
     574                 : 
     575                 : {
     576                 :     {
     577                 :         "hex",
     578                 :         {
     579                 :             hex_enc_len, hex_dec_len, hex_encode, hex_decode
     580                 :         }
     581                 :     },
     582                 :     {
     583                 :         "base64",
     584                 :         {
     585                 :             pg_base64_enc_len, pg_base64_dec_len, pg_base64_encode, pg_base64_decode
     586                 :         }
     587                 :     },
     588                 :     {
     589                 :         "escape",
     590                 :         {
     591                 :             esc_enc_len, esc_dec_len, esc_encode, esc_decode
     592                 :         }
     593                 :     },
     594                 :     {
     595                 :         NULL,
     596                 :         {
     597                 :             NULL, NULL, NULL, NULL
     598                 :         }
     599                 :     }
     600                 : };
     601                 : 
     602                 : static const struct pg_encoding *
     603 GIC      115635 : pg_find_encoding(const char *name)
     604                 : {
     605                 :     int         i;
     606                 : 
     607          115734 :     for (i = 0; enclist[i].name; i++)
     608          115734 :         if (pg_strcasecmp(enclist[i].name, name) == 0)
     609          115635 :             return &enclist[i].enc;
     610                 : 
     611 UIC           0 :     return NULL;
     612                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a