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 : }
|