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 17:13:01 Functions: 100.0 % 17 17 15 2 17
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 90.9 % 11 10 1 10
Legend: Lines: hit not hit (240..) days: 88.7 % 212 188 17 7 4 112 72 20 100
Function coverage date bins:
(60,120] days: 100.0 % 2 2 2
(240..) days: 48.4 % 31 15 15 16

 Age         Owner                  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
 7941 bruce                      48 GIC       99209 : binary_encode(PG_FUNCTION_ARGS)
 7941 bruce                      49 ECB             : {
 2219 noah                       50 GIC       99209 :     bytea      *data = PG_GETARG_BYTEA_PP(0);
 7941 bruce                      51 CBC       99209 :     Datum       name = PG_GETARG_DATUM(1);
 7941 bruce                      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                 : 
 5493 tgl                        60 GIC       99209 :     namebuf = TextDatumGetCString(name);
 7941 bruce                      61 ECB             : 
 7941 bruce                      62 GIC       99209 :     enc = pg_find_encoding(namebuf);
 7941 bruce                      63 CBC       99209 :     if (enc == NULL)
 7196 tgl                        64 LBC           0 :         ereport(ERROR,
 7196 tgl                        65 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 66                 :                  errmsg("unrecognized encoding: \"%s\"", namebuf)));
                                 67                 : 
 1097 tgl                        68 GIC       99209 :     dataptr = VARDATA_ANY(data);
 1097 tgl                        69 CBC       99209 :     datalen = VARSIZE_ANY_EXHDR(data);
 1097 tgl                        70 ECB             : 
 1097 tgl                        71 GIC       99209 :     resultlen = enc->encode_len(dataptr, datalen);
 1097 tgl                        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                 :      */
 1097 tgl                        77 GIC       99209 :     if (resultlen > MaxAllocSize - VARHDRSZ)
 1097 tgl                        78 LBC           0 :         ereport(ERROR,
 1097 tgl                        79 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                 80                 :                  errmsg("result of encoding conversion is too large")));
                                 81                 : 
 7941 bruce                      82 GIC       99209 :     result = palloc(VARHDRSZ + resultlen);
 7941 bruce                      83 ECB             : 
  598 michael                    84 GIC       99209 :     res = enc->encode(dataptr, datalen, VARDATA(result));
  598 michael                    85 ECB             : 
                                 86                 :     /* Make this FATAL 'cause we've trodden on memory ... */
  598 michael                    87 GIC       99209 :     if (res > resultlen)
  598 michael                    88 LBC           0 :         elog(FATAL, "overflow - encode estimate too small");
 7941 bruce                      89 EUB             : 
 5885 tgl                        90 GIC       99209 :     SET_VARSIZE(result, VARHDRSZ + res);
 7941 bruce                      91 ECB             : 
 7941 bruce                      92 GIC       99209 :     PG_RETURN_TEXT_P(result);
 7941 bruce                      93 ECB             : }
                                 94                 : 
                                 95                 : Datum
 7941 bruce                      96 GIC       16426 : binary_decode(PG_FUNCTION_ARGS)
 7941 bruce                      97 ECB             : {
 2219 noah                       98 GIC       16426 :     text       *data = PG_GETARG_TEXT_PP(0);
 7941 bruce                      99 CBC       16426 :     Datum       name = PG_GETARG_DATUM(1);
 7941 bruce                     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                 : 
 5493 tgl                       108 GIC       16426 :     namebuf = TextDatumGetCString(name);
 7941 bruce                     109 ECB             : 
 7941 bruce                     110 GIC       16426 :     enc = pg_find_encoding(namebuf);
 7941 bruce                     111 CBC       16426 :     if (enc == NULL)
 7196 tgl                       112 LBC           0 :         ereport(ERROR,
 7196 tgl                       113 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                114                 :                  errmsg("unrecognized encoding: \"%s\"", namebuf)));
                                115                 : 
 1097 tgl                       116 GIC       16426 :     dataptr = VARDATA_ANY(data);
 1097 tgl                       117 CBC       16426 :     datalen = VARSIZE_ANY_EXHDR(data);
 1097 tgl                       118 ECB             : 
 1097 tgl                       119 GIC       16426 :     resultlen = enc->decode_len(dataptr, datalen);
 1097 tgl                       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                 :      */
 1097 tgl                       125 GIC       16426 :     if (resultlen > MaxAllocSize - VARHDRSZ)
 1097 tgl                       126 LBC           0 :         ereport(ERROR,
 1097 tgl                       127 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                128                 :                  errmsg("result of decoding conversion is too large")));
                                129                 : 
 7941 bruce                     130 GIC       16426 :     result = palloc(VARHDRSZ + resultlen);
 7941 bruce                     131 ECB             : 
  598 michael                   132 GIC       16426 :     res = enc->decode(dataptr, datalen, VARDATA(result));
  598 michael                   133 ECB             : 
                                134                 :     /* Make this FATAL 'cause we've trodden on memory ... */
  598 michael                   135 GIC       16426 :     if (res > resultlen)
  598 michael                   136 LBC           0 :         elog(FATAL, "overflow - decode estimate too small");
 7941 bruce                     137 EUB             : 
 5885 tgl                       138 GIC       16426 :     SET_VARSIZE(result, VARHDRSZ + res);
 7941 bruce                     139 ECB             : 
 7941 bruce                     140 GIC       16426 :     PG_RETURN_BYTEA_P(result);
 7941 bruce                     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
  598 michael                   162 GIC      224346 : hex_encode(const char *src, size_t len, char *dst)
  598 michael                   163 ECB             : {
  598 michael                   164 GIC      224346 :     const char *end = src + len;
  598 michael                   165 ECB             : 
  598 michael                   166 GIC     4117982 :     while (src < end)
  598 michael                   167 ECB             :     {
  598 michael                   168 GIC     3893636 :         *dst++ = hextbl[(*src >> 4) & 0xF];
  598 michael                   169 CBC     3893636 :         *dst++ = hextbl[*src & 0xF];
                                170         3893636 :         src++;
  598 michael                   171 ECB             :     }
  598 michael                   172 GIC      224346 :     return (uint64) len * 2;
  598 michael                   173 ECB             : }
                                174                 : 
                                175                 : static inline bool
  116 tgl                       176 GNC      432945 : get_hex(const char *cp, char *out)
  598 michael                   177 ECB             : {
  598 michael                   178 GIC      432945 :     unsigned char c = (unsigned char) *cp;
  598 michael                   179 CBC      432945 :     int         res = -1;
  598 michael                   180 ECB             : 
  598 michael                   181 GIC      432945 :     if (c < 127)
  598 michael                   182 CBC      432945 :         res = hexlookup[c];
  598 michael                   183 ECB             : 
  116 tgl                       184 GNC      432945 :     *out = (char) res;
                                185                 : 
                                186          432945 :     return (res >= 0);
  598 michael                   187 ECB             : }
                                188                 : 
                                189                 : uint64
  598 michael                   190 GIC       16406 : hex_decode(const char *src, size_t len, char *dst)
                                191                 : {
  116 tgl                       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,
  598 michael                   199 ECB             :                *srcend;
                                200                 :     char        v1,
                                201                 :                 v2,
                                202                 :                *p;
                                203                 : 
  598 michael                   204 GIC       16811 :     srcend = src + len;
                                205           16811 :     s = src;
                                206           16811 :     p = dst;
  598 michael                   207 CBC      233303 :     while (s < srcend)
  598 michael                   208 ECB             :     {
  598 michael                   209 CBC      216507 :         if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
  598 michael                   210 ECB             :         {
  598 michael                   211 GIC          30 :             s++;
  598 michael                   212 CBC          30 :             continue;
                                213                 :         }
  116 tgl                       214 GNC      216477 :         if (!get_hex(s, &v1))
  116 tgl                       215 UNC           0 :             ereturn(escontext, 0,
                                216                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                217                 :                      errmsg("invalid hexadecimal digit: \"%.*s\"",
                                218                 :                             pg_mblen(s), s)));
  598 michael                   219 CBC      216477 :         s++;
  598 michael                   220 GIC      216477 :         if (s >= srcend)
  116 tgl                       221 GNC           9 :             ereturn(escontext, 0,
  598 michael                   222 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                223                 :                      errmsg("invalid hexadecimal data: odd number of digits")));
  116 tgl                       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)));
  598 michael                   229 CBC      216462 :         s++;
  116 tgl                       230 GNC      216462 :         *p++ = (v1 << 4) | v2;
  598 michael                   231 ECB             :     }
                                232                 : 
  598 michael                   233 GIC       16796 :     return p - dst;
  598 michael                   234 ECB             : }
                                235                 : 
                                236                 : static uint64
 1097 tgl                       237 GIC       99174 : hex_enc_len(const char *src, size_t srclen)
                                238                 : {
  598 michael                   239 CBC       99174 :     return (uint64) srclen << 1;
 7941 bruce                     240 ECB             : }
                                241                 : 
                                242                 : static uint64
 1097 tgl                       243 CBC       16406 : hex_dec_len(const char *src, size_t srclen)
                                244                 : {
  598 michael                   245 GIC       16406 :     return (uint64) srclen >> 1;
                                246                 : }
 7941 bruce                     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
  598 michael                   267 GIC           6 : pg_base64_encode(const char *src, size_t len, char *dst)
                                268                 : {
                                269                 :     char       *p,
 7941 bruce                     270               6 :                *lend = dst + 76;
                                271                 :     const char *s,
  598 michael                   272               6 :                *end = src + len;
 7941 bruce                     273               6 :     int         pos = 2;
                                274               6 :     uint32      buf = 0;
                                275                 : 
                                276               6 :     s = src;
 7941 bruce                     277 CBC           6 :     p = dst;
                                278                 : 
 7941 bruce                     279 GIC         426 :     while (s < end)
 7941 bruce                     280 ECB             :     {
 6406 tgl                       281 GIC         420 :         buf |= (unsigned char) *s << (pos << 3);
 7941 bruce                     282 CBC         420 :         pos--;
                                283             420 :         s++;
 7941 bruce                     284 ECB             : 
                                285                 :         /* write it out */
 7941 bruce                     286 CBC         420 :         if (pos < 0)
 7941 bruce                     287 ECB             :         {
 7941 bruce                     288 GIC         138 :             *p++ = _base64[(buf >> 18) & 0x3f];
 7941 bruce                     289 CBC         138 :             *p++ = _base64[(buf >> 12) & 0x3f];
 7941 bruce                     290 GIC         138 :             *p++ = _base64[(buf >> 6) & 0x3f];
 7941 bruce                     291 CBC         138 :             *p++ = _base64[buf & 0x3f];
 7941 bruce                     292 ECB             : 
 7941 bruce                     293 CBC         138 :             pos = 2;
 7941 bruce                     294 GIC         138 :             buf = 0;
                                295                 :         }
 7941 bruce                     296 CBC         420 :         if (p >= lend)
                                297                 :         {
                                298               6 :             *p++ = '\n';
                                299               6 :             lend = p + 76;
 7941 bruce                     300 ECB             :         }
                                301                 :     }
 7941 bruce                     302 GIC           6 :     if (pos != 2)
 7941 bruce                     303 ECB             :     {
 7941 bruce                     304 CBC           6 :         *p++ = _base64[(buf >> 18) & 0x3f];
 7941 bruce                     305 GIC           6 :         *p++ = _base64[(buf >> 12) & 0x3f];
 7941 bruce                     306 CBC           6 :         *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
 7941 bruce                     307 GIC           6 :         *p++ = '=';
 7941 bruce                     308 ECB             :     }
                                309                 : 
 7941 bruce                     310 GIC           6 :     return p - dst;
                                311                 : }
 7941 bruce                     312 ECB             : 
                                313                 : static uint64
  598 michael                   314 CBC           5 : pg_base64_decode(const char *src, size_t len, char *dst)
 7941 bruce                     315 ECB             : {
  598 michael                   316 CBC           5 :     const char *srcend = src + len,
 7941 bruce                     317               5 :                *s = src;
 6406 tgl                       318 GIC           5 :     char       *p = dst;
                                319                 :     char        c;
 7941 bruce                     320 CBC           5 :     int         b = 0;
 7941 bruce                     321 GIC           5 :     uint32      buf = 0;
                                322               5 :     int         pos = 0,
                                323               5 :                 end = 0;
 7941 bruce                     324 ECB             : 
 7941 bruce                     325 GIC         312 :     while (s < srcend)
 7941 bruce                     326 ECB             :     {
 7941 bruce                     327 CBC         307 :         c = *s++;
 7941 bruce                     328 ECB             : 
 7941 bruce                     329 GIC         307 :         if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
 7941 bruce                     330 CBC           3 :             continue;
 7941 bruce                     331 ECB             : 
 7941 bruce                     332 CBC         304 :         if (c == '=')
 7941 bruce                     333 ECB             :         {
                                334                 :             /* end sequence */
 7941 bruce                     335 CBC           8 :             if (!end)
                                336                 :             {
                                337               5 :                 if (pos == 2)
 7941 bruce                     338 GIC           3 :                     end = 1;
 7941 bruce                     339 CBC           2 :                 else if (pos == 3)
                                340               2 :                     end = 2;
                                341                 :                 else
 7196 tgl                       342 LBC           0 :                     ereport(ERROR,
                                343                 :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                344                 :                              errmsg("unexpected \"=\" while decoding base64 sequence")));
 7941 bruce                     345 ECB             :             }
 7941 bruce                     346 GIC           8 :             b = 0;
 7941 bruce                     347 ECB             :         }
 7836                           348                 :         else
                                349                 :         {
 7941 bruce                     350 CBC         296 :             b = -1;
 7941 bruce                     351 GIC         296 :             if (c > 0 && c < 127)
 6406 tgl                       352 GBC         296 :                 b = b64lookup[(unsigned char) c];
 7941 bruce                     353 GIC         296 :             if (b < 0)
 7196 tgl                       354 UIC           0 :                 ereport(ERROR,
                                355                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 1014 tgl                       356 ECB             :                          errmsg("invalid symbol \"%.*s\" found while decoding base64 sequence",
                                357                 :                                 pg_mblen(s - 1), s - 1)));
                                358                 :         }
                                359                 :         /* add it to buffer */
 7941 bruce                     360 CBC         304 :         buf = (buf << 6) + b;
                                361             304 :         pos++;
                                362             304 :         if (pos == 4)
 7941 bruce                     363 ECB             :         {
 7941 bruce                     364 GBC          76 :             *p++ = (buf >> 16) & 255;
 7941 bruce                     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;
 7941 bruce                     370 CBC          76 :             pos = 0;
 7941 bruce                     371 ECB             :         }
                                372                 :     }
                                373                 : 
 7941 bruce                     374 CBC           5 :     if (pos != 0)
 7196 tgl                       375 LBC           0 :         ereport(ERROR,
 7196 tgl                       376 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3196 rhaas                     377                 :                  errmsg("invalid base64 end sequence"),
 2701 peter_e                   378                 :                  errhint("Input data is missing padding, is truncated, or is otherwise corrupted.")));
 7941 bruce                     379                 : 
 7941 bruce                     380 CBC           5 :     return p - dst;
                                381                 : }
                                382                 : 
                                383                 : 
 1097 tgl                       384 ECB             : static uint64
 1097 tgl                       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 */
 1097 tgl                       388 GIC           6 :     return ((uint64) srclen + 2) * 4 / 3 + (uint64) srclen / (76 * 3 / 4);
                                389                 : }
 7941 bruce                     390 ECB             : 
                                391                 : static uint64
 1097 tgl                       392 GIC           5 : pg_base64_dec_len(const char *src, size_t srclen)
                                393                 : {
                                394               5 :     return ((uint64) srclen * 3) >> 2;
 7941 bruce                     395 ECB             : }
                                396                 : 
                                397                 : /*
 7877                           398                 :  * Escape
                                399                 :  * Minimally escape bytea to text.
                                400                 :  * De-escape text to bytea.
                                401                 :  *
 5521 tgl                       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
  598 michael                   415 GIC          29 : esc_encode(const char *src, size_t srclen, char *dst)
                                416                 : {
 6406 tgl                       417              29 :     const char *end = src + srclen;
                                418              29 :     char       *rp = dst;
 1097                           419              29 :     uint64      len = 0;
                                420                 : 
 7877 bruce                     421             261 :     while (src < end)
                                422                 :     {
 5521 tgl                       423             232 :         unsigned char c = (unsigned char) *src;
                                424                 : 
 5521 tgl                       425 CBC         232 :         if (c == '\0' || IS_HIGHBIT_SET(c))
                                426                 :         {
 7877 bruce                     427              42 :             rp[0] = '\\';
 5521 tgl                       428              42 :             rp[1] = DIG(c >> 6);
                                429              42 :             rp[2] = DIG((c >> 3) & 7);
 5521 tgl                       430 GIC          42 :             rp[3] = DIG(c & 7);
 7877 bruce                     431 CBC          42 :             rp += 4;
 7877 bruce                     432 GIC          42 :             len += 4;
 7877 bruce                     433 ECB             :         }
 5521 tgl                       434 GIC         190 :         else if (c == '\\')
 7877 bruce                     435 ECB             :         {
 7877 bruce                     436 UIC           0 :             rp[0] = '\\';
 7877 bruce                     437 LBC           0 :             rp[1] = '\\';
                                438               0 :             rp += 2;
                                439               0 :             len += 2;
 7877 bruce                     440 ECB             :         }
                                441                 :         else
                                442                 :         {
 5521 tgl                       443 GIC         190 :             *rp++ = c;
 7877 bruce                     444 CBC         190 :             len++;
                                445                 :         }
 7877 bruce                     446 EUB             : 
 7877 bruce                     447 GBC         232 :         src++;
 7877 bruce                     448 EUB             :     }
                                449                 : 
 7877 bruce                     450 GIC          29 :     return len;
                                451                 : }
                                452                 : 
 1097 tgl                       453 ECB             : static uint64
  598 michael                   454 CBC          15 : esc_decode(const char *src, size_t srclen, char *dst)
                                455                 : {
 6406 tgl                       456 GIC          15 :     const char *end = src + srclen;
 6406 tgl                       457 CBC          15 :     char       *rp = dst;
 1097 tgl                       458 GIC          15 :     uint64      len = 0;
                                459                 : 
 7877 bruce                     460 CBC     1200042 :     while (src < end)
                                461                 :     {
 7877 bruce                     462 GIC     1200027 :         if (src[0] != '\\')
                                463         1200012 :             *rp++ = *src++;
 7836 bruce                     464 CBC          15 :         else if (src + 3 < end &&
 7836 bruce                     465 GIC          15 :                  (src[1] >= '0' && src[1] <= '3') &&
 7836 bruce                     466 CBC          15 :                  (src[2] >= '0' && src[2] <= '7') &&
                                467              15 :                  (src[3] >= '0' && src[3] <= '7'))
 7877                           468              15 :         {
                                469                 :             int         val;
 7861 tgl                       470 ECB             : 
 7877 bruce                     471 GIC          15 :             val = VAL(src[1]);
 7877 bruce                     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;
 7877 bruce                     477 ECB             :         }
 7836 bruce                     478 LBC           0 :         else if (src + 1 < end &&
 7836 bruce                     479 UIC           0 :                  (src[1] == '\\'))
                                480                 :         {
 7877 bruce                     481 LBC           0 :             *rp++ = '\\';
                                482               0 :             src += 2;
 7877 bruce                     483 ECB             :         }
                                484                 :         else
                                485                 :         {
                                486                 :             /*
                                487                 :              * One backslash, not followed by ### valid octal. Should never
 6385 bruce                     488 EUB             :              * get here, since esc_dec_len does same check.
 7877                           489                 :              */
 7196 tgl                       490 UIC           0 :             ereport(ERROR,
 7196 tgl                       491 EUB             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 2272 alvherre                  492                 :                      errmsg("invalid input syntax for type %s", "bytea")));
                                493                 :         }
                                494                 : 
 7877 bruce                     495 GIC     1200027 :         len++;
                                496                 :     }
                                497                 : 
                                498              15 :     return len;
                                499                 : }
 7877 bruce                     500 EUB             : 
                                501                 : static uint64
 1097 tgl                       502 GIC          29 : esc_enc_len(const char *src, size_t srclen)
                                503                 : {
 6406                           504              29 :     const char *end = src + srclen;
 1097 tgl                       505 CBC          29 :     uint64      len = 0;
                                506                 : 
 7877 bruce                     507 GIC         261 :     while (src < end)
 7877 bruce                     508 ECB             :     {
 5521 tgl                       509 GIC         232 :         if (*src == '\0' || IS_HIGHBIT_SET(*src))
 7877 bruce                     510              42 :             len += 4;
                                511             190 :         else if (*src == '\\')
 7877 bruce                     512 LBC           0 :             len += 2;
                                513                 :         else
 7877 bruce                     514 CBC         190 :             len++;
 7877 bruce                     515 ECB             : 
 7877 bruce                     516 GIC         232 :         src++;
 7877 bruce                     517 ECB             :     }
                                518                 : 
 7877 bruce                     519 CBC          29 :     return len;
 7877 bruce                     520 ECB             : }
                                521                 : 
 1097 tgl                       522 EUB             : static uint64
 1097 tgl                       523 GIC          15 : esc_dec_len(const char *src, size_t srclen)
 7877 bruce                     524 ECB             : {
 6406 tgl                       525 GIC          15 :     const char *end = src + srclen;
 1097 tgl                       526 CBC          15 :     uint64      len = 0;
                                527                 : 
 7877 bruce                     528 GIC     1200042 :     while (src < end)
 7877 bruce                     529 ECB             :     {
 7877 bruce                     530 GIC     1200027 :         if (src[0] != '\\')
                                531         1200012 :             src++;
 7836                           532              15 :         else if (src + 3 < end &&
 7836 bruce                     533 CBC          15 :                  (src[1] >= '0' && src[1] <= '3') &&
 7836 bruce                     534 GIC          15 :                  (src[2] >= '0' && src[2] <= '7') &&
 7836 bruce                     535 CBC          15 :                  (src[3] >= '0' && src[3] <= '7'))
 7877 bruce                     536 ECB             :         {
                                537                 :             /*
                                538                 :              * backslash + valid octal
                                539                 :              */
 7877 bruce                     540 CBC          15 :             src += 4;
 7877 bruce                     541 ECB             :         }
 7836 bruce                     542 LBC           0 :         else if (src + 1 < end &&
                                543               0 :                  (src[1] == '\\'))
 7877 bruce                     544 ECB             :         {
                                545                 :             /*
                                546                 :              * two backslashes = backslash
                                547                 :              */
 7877 bruce                     548 UIC           0 :             src += 2;
                                549                 :         }
 7877 bruce                     550 ECB             :         else
                                551                 :         {
 7877 bruce                     552 EUB             :             /*
                                553                 :              * one backslash, not followed by ### valid octal
                                554                 :              */
 7196 tgl                       555 UIC           0 :             ereport(ERROR,
                                556                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                                557                 :                      errmsg("invalid input syntax for type %s", "bytea")));
 7877 bruce                     558 EUB             :         }
                                559                 : 
 7877 bruce                     560 GIC     1200027 :         len++;
                                561                 :     }
                                562              15 :     return len;
                                563                 : }
                                564                 : 
 7941 bruce                     565 EUB             : /*
                                566                 :  * Common
                                567                 :  */
                                568                 : 
                                569                 : static const struct
 7836 bruce                     570 ECB             : {
                                571                 :     const char *name;
 7941                           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 *
 7941 bruce                     603 GIC      115635 : pg_find_encoding(const char *name)
                                604                 : {
                                605                 :     int         i;
                                606                 : 
                                607          115734 :     for (i = 0; enclist[i].name; i++)
 6911 tgl                       608          115734 :         if (pg_strcasecmp(enclist[i].name, name) == 0)
 7941 bruce                     609          115635 :             return &enclist[i].enc;
                                610                 : 
 7941 bruce                     611 UIC           0 :     return NULL;
                                612                 : }
        

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