products/Sources/formale Sprachen/C/Postgres/src/include/optimizer/   (Postgres Database Version 18.4©)  Datei vom 11.4.2026 mit Größe 2 kB image not shown  

SSL encode.c   Sprache: unbekannt

 
/*-------------------------------------------------------------------------
 *
 * encode.c
 *   Various data encoding/decoding things.
 *
 * Copyright (c) 2001-2025, PostgreSQL Global Development Group
 *
 *
 * IDENTIFICATION
 *   src/backend/utils/adt/encode.c
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include <ctype.h>

#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "varatt.h"


/*
 * Encoding conversion API.
 * encode_len() and decode_len() compute the amount of space needed, while
 * encode() and decode() perform the actual conversions.  It is okay for
 * the _len functions to return an overestimate, but not an underestimate.
 * (Having said that, large overestimates could cause unnecessary errors,
 * so it's better to get it right.)  The conversion routines write to the
 * buffer at *res and return the true length of their output.
 */

struct pg_encoding
{
 uint64  (*encode_len) (const char *data, size_t dlen);
 uint64  (*decode_len) (const char *data, size_t dlen);
 uint64  (*encode) (const char *data, size_t dlen, char *res);
 uint64  (*decode) (const char *data, size_t dlen, char *res);
};

static const struct pg_encoding *pg_find_encoding(const char *name);

/*
 * SQL functions.
 */


Datum
binary_encode(PG_FUNCTION_ARGS)
{
 bytea    *data = PG_GETARG_BYTEA_PP(0);
 Datum  name = PG_GETARG_DATUM(1);
 text    *result;
 char    *namebuf;
 char    *dataptr;
 size_t  datalen;
 uint64  resultlen;
 uint64  res;
 const struct pg_encoding *enc;

 namebuf = TextDatumGetCString(name);

 enc = pg_find_encoding(namebuf);
 if (enc == NULL)
  ereport(ERROR,
    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     errmsg("unrecognized encoding: \"%s\"", namebuf)));

 dataptr = VARDATA_ANY(data);
 datalen = VARSIZE_ANY_EXHDR(data);

 resultlen = enc->encode_len(dataptr, datalen);

 /*
  * resultlen possibly overflows uint32, therefore on 32-bit machines it's
  * unsafe to rely on palloc's internal check.
 */

 if (resultlen > MaxAllocSize - VARHDRSZ)
  ereport(ERROR,
    (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     errmsg("result of encoding conversion is too large")));

 result = palloc(VARHDRSZ + resultlen);

 res = enc->encode(dataptr, datalen, VARDATA(result));

 /* Make this FATAL 'cause we've trodden on memory ... */
 if (res > resultlen)
  elog(FATAL, "overflow - encode estimate too small");

 SET_VARSIZE(result, VARHDRSZ + res);

 PG_RETURN_TEXT_P(result);
}

Datum
binary_decode(PG_FUNCTION_ARGS)
{
 text    *data = PG_GETARG_TEXT_PP(0);
 Datum  name = PG_GETARG_DATUM(1);
 bytea    *result;
 char    *namebuf;
 char    *dataptr;
 size_t  datalen;
 uint64  resultlen;
 uint64  res;
 const struct pg_encoding *enc;

 namebuf = TextDatumGetCString(name);

 enc = pg_find_encoding(namebuf);
 if (enc == NULL)
  ereport(ERROR,
    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     errmsg("unrecognized encoding: \"%s\"", namebuf)));

 dataptr = VARDATA_ANY(data);
 datalen = VARSIZE_ANY_EXHDR(data);

 resultlen = enc->decode_len(dataptr, datalen);

 /*
  * resultlen possibly overflows uint32, therefore on 32-bit machines it's
  * unsafe to rely on palloc's internal check.
 */

 if (resultlen > MaxAllocSize - VARHDRSZ)
  ereport(ERROR,
    (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     errmsg("result of decoding conversion is too large")));

 result = palloc(VARHDRSZ + resultlen);

 res = enc->decode(dataptr, datalen, VARDATA(result));

 /* Make this FATAL 'cause we've trodden on memory ... */
 if (res > resultlen)
  elog(FATAL, "overflow - decode estimate too small");

 SET_VARSIZE(result, VARHDRSZ + res);

 PG_RETURN_BYTEA_P(result);
}


/*
 * HEX
 */


/*
 * The hex expansion of each possible byte value (two chars per value).
 */

static const char hextbl[512] =
"000102030405060708090a0b0c0d0e0f"
"101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f"
"303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f"
"505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f"
"707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f"
"909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";

static const int8 hexlookup[128] = {
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 0123456789, -1, -1, -1, -1, -1, -1,
 -1101112131415, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 -1101112131415, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};

uint64
hex_encode(const char *src, size_t len, char *dst)
{
 const char *end = src + len;

 while (src < end)
 {
  unsigned char usrc = *((const unsigned char *) src);

  memcpy(dst, &hextbl[2 * usrc], 2);
  src++;
  dst += 2;
 }
 return (uint64) len * 2;
}

static inline bool
get_hex(const char *cp, char *out)
{
 unsigned char c = (unsigned char) *cp;
 int   res = -1;

 if (c < 127)
  res = hexlookup[c];

 *out = (char) res;

 return (res >= 0);
}

uint64
hex_decode(const char *src, size_t len, char *dst)
{
 return hex_decode_safe(src, len, dst, NULL);
}

uint64
hex_decode_safe(const char *src, size_t len, char *dst, Node *escontext)
{
 const char *s,
      *srcend;
 char  v1,
    v2,
      *p;

 srcend = src + len;
 s = src;
 p = dst;
 while (s < srcend)
 {
  if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
  {
   s++;
   continue;
  }
  if (!get_hex(s, &v1))
   ereturn(escontext, 0,
     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      errmsg("invalid hexadecimal digit: \"%.*s\"",
       pg_mblen_range(s, srcend), s)));
  s++;
  if (s >= srcend)
   ereturn(escontext, 0,
     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      errmsg("invalid hexadecimal data: odd number of digits")));
  if (!get_hex(s, &v2))
   ereturn(escontext, 0,
     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      errmsg("invalid hexadecimal digit: \"%.*s\"",
       pg_mblen_range(s, srcend), s)));
  s++;
  *p++ = (v1 << 4) | v2;
 }

 return p - dst;
}

static uint64
hex_enc_len(const char *src, size_t srclen)
{
 return (uint64) srclen << 1;
}

static uint64
hex_dec_len(const char *src, size_t srclen)
{
 return (uint64) srclen >> 1;
}

/*
 * BASE64
 */


static const char _base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static const int8 b64lookup[128] = {
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -162, -1, -1, -163,
 52535455565758596061, -1, -1, -1, -1, -1, -1,
 -101234567891011121314,
 1516171819202122232425, -1, -1, -1, -1, -1,
 -1262728293031323334353637383940,
 4142434445464748495051, -1, -1, -1, -1, -1,
};

static uint64
pg_base64_encode(const char *src, size_t len, char *dst)
{
 char    *p,
      *lend = dst + 76;
 const char *s,
      *end = src + len;
 int   pos = 2;
 uint32  buf = 0;

 s = src;
 p = dst;

 while (s < end)
 {
  buf |= (unsigned char) *s << (pos << 3);
  pos--;
  s++;

  /* write it out */
  if (pos < 0)
  {
   *p++ = _base64[(buf >> 18) & 0x3f];
   *p++ = _base64[(buf >> 12) & 0x3f];
   *p++ = _base64[(buf >> 6) & 0x3f];
   *p++ = _base64[buf & 0x3f];

   pos = 2;
   buf = 0;
  }
  if (p >= lend)
  {
   *p++ = '\n';
   lend = p + 76;
  }
 }
 if (pos != 2)
 {
  *p++ = _base64[(buf >> 18) & 0x3f];
  *p++ = _base64[(buf >> 12) & 0x3f];
  *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
  *p++ = '=';
 }

 return p - dst;
}

static uint64
pg_base64_decode(const char *src, size_t len, char *dst)
{
 const char *srcend = src + len,
      *s = src;
 char    *p = dst;
 char  c;
 int   b = 0;
 uint32  buf = 0;
 int   pos = 0,
    end = 0;

 while (s < srcend)
 {
  c = *s++;

  if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
   continue;

  if (c == '=')
  {
   /* end sequence */
   if (!end)
   {
    if (pos == 2)
     end = 1;
    else if (pos == 3)
     end = 2;
    else
     ereport(ERROR,
       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
        errmsg("unexpected \"=\" while decoding base64 sequence")));
   }
   b = 0;
  }
  else
  {
   b = -1;
   if (c > 0 && c < 127)
    b = b64lookup[(unsigned char) c];
   if (b < 0)
    ereport(ERROR,
      (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
       errmsg("invalid symbol \"%.*s\" found while decoding base64 sequence",
        pg_mblen_range(s - 1, srcend), s - 1)));
  }
  /* add it to buffer */
  buf = (buf << 6) + b;
  pos++;
  if (pos == 4)
  {
   *p++ = (buf >> 16) & 255;
   if (end == 0 || end > 1)
    *p++ = (buf >> 8) & 255;
   if (end == 0 || end > 2)
    *p++ = buf & 255;
   buf = 0;
   pos = 0;
  }
 }

 if (pos != 0)
  ereport(ERROR,
    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     errmsg("invalid base64 end sequence"),
     errhint("Input data is missing padding, is truncated, or is otherwise corrupted.")));

 return p - dst;
}


static uint64
pg_base64_enc_len(const char *src, size_t srclen)
{
 /* 3 bytes will be converted to 4, linefeed after 76 chars */
 return ((uint64) srclen + 2) / 3 * 4 + (uint64) srclen / (76 * 3 / 4);
}

static uint64
pg_base64_dec_len(const char *src, size_t srclen)
{
 return ((uint64) srclen * 3) >> 2;
}

/*
 * Escape
 * Minimally escape bytea to text.
 * De-escape text to bytea.
 *
 * We must escape zero bytes and high-bit-set bytes to avoid generating
 * text that might be invalid in the current encoding, or that might
 * change to something else if passed through an encoding conversion
 * (leading to failing to de-escape to the original bytea value).
 * Also of course backslash itself has to be escaped.
 *
 * De-escaping processes \\ and any \### octal
 */


#define VAL(CH)   ((CH) - '0')
#define DIG(VAL)  ((VAL) + '0')

static uint64
esc_encode(const char *src, size_t srclen, char *dst)
{
 const char *end = src + srclen;
 char    *rp = dst;
 uint64  len = 0;

 while (src < end)
 {
  unsigned char c = (unsigned char) *src;

  if (c == '\0' || IS_HIGHBIT_SET(c))
  {
   rp[0] = '\\';
   rp[1] = DIG(c >> 6);
   rp[2] = DIG((c >> 3) & 7);
   rp[3] = DIG(c & 7);
   rp += 4;
   len += 4;
  }
  else if (c == '\\')
  {
   rp[0] = '\\';
   rp[1] = '\\';
   rp += 2;
   len += 2;
  }
  else
  {
   *rp++ = c;
   len++;
  }

  src++;
 }

 return len;
}

static uint64
esc_decode(const char *src, size_t srclen, char *dst)
{
 const char *end = src + srclen;
 char    *rp = dst;
 uint64  len = 0;

 while (src < end)
 {
  if (src[0] != '\\')
   *rp++ = *src++;
  else if (src + 3 < end &&
     (src[1] >= '0' && src[1] <= '3') &&
     (src[2] >= '0' && src[2] <= '7') &&
     (src[3] >= '0' && src[3] <= '7'))
  {
   int   val;

   val = VAL(src[1]);
   val <<= 3;
   val += VAL(src[2]);
   val <<= 3;
   *rp++ = val + VAL(src[3]);
   src += 4;
  }
  else if (src + 1 < end &&
     (src[1] == '\\'))
  {
   *rp++ = '\\';
   src += 2;
  }
  else
  {
   /*
    * One backslash, not followed by ### valid octal. Should never
    * get here, since esc_dec_len does same check.
 */

   ereport(ERROR,
     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      errmsg("invalid input syntax for type %s""bytea")));
  }

  len++;
 }

 return len;
}

static uint64
esc_enc_len(const char *src, size_t srclen)
{
 const char *end = src + srclen;
 uint64  len = 0;

 while (src < end)
 {
  if (*src == '\0' || IS_HIGHBIT_SET(*src))
   len += 4;
  else if (*src == '\\')
   len += 2;
  else
   len++;

  src++;
 }

 return len;
}

static uint64
esc_dec_len(const char *src, size_t srclen)
{
 const char *end = src + srclen;
 uint64  len = 0;

 while (src < end)
 {
  if (src[0] != '\\')
   src++;
  else if (src + 3 < end &&
     (src[1] >= '0' && src[1] <= '3') &&
     (src[2] >= '0' && src[2] <= '7') &&
     (src[3] >= '0' && src[3] <= '7'))
  {
   /*
    * backslash + valid octal
 */

   src += 4;
  }
  else if (src + 1 < end &&
     (src[1] == '\\'))
  {
   /*
    * two backslashes = backslash
 */

   src += 2;
  }
  else
  {
   /*
    * one backslash, not followed by ### valid octal
 */

   ereport(ERROR,
     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      errmsg("invalid input syntax for type %s""bytea")));
  }

  len++;
 }
 return len;
}

/*
 * Common
 */


static const struct
{
 const char *name;
 struct pg_encoding enc;
}   enclist[] =

{
 {
  "hex",
  {
   hex_enc_len, hex_dec_len, hex_encode, hex_decode
  }
 },
 {
  "base64",
  {
   pg_base64_enc_len, pg_base64_dec_len, pg_base64_encode, pg_base64_decode
  }
 },
 {
  "escape",
  {
   esc_enc_len, esc_dec_len, esc_encode, esc_decode
  }
 },
 {
  NULL,
  {
   NULL, NULL, NULL, NULL
  }
 }
};

static const struct pg_encoding *
pg_find_encoding(const char *name)
{
 int   i;

 for (i = 0; enclist[i].name; i++)
  if (pg_strcasecmp(enclist[i].name, name) == 0)
   return &enclist[i].enc;

 return NULL;
}

Messung V0.5 in Prozent
C=94 H=93 G=93

[Verzeichnis aufwärts0.84unsichere VerbindungÜbersetzung europäischer Sprachen durch Browser2026-08-08]