From c3826f831e6e63e13a749fd3ab9fd7106707b549 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 24 Dec 2020 17:25:48 -0500 Subject: [PATCH] move hex_decode() to /common so it can be called from frontend This allows removal of a copy of hex_decode() from ecpg, and will be used by the soon-to-be added pg_alterckey command. Backpatch-through: master --- src/backend/utils/adt/encode.c | 64 +---------------- src/backend/utils/adt/varlena.c | 1 + src/common/Makefile | 1 + src/common/hex_decode.c | 106 +++++++++++++++++++++++++++++ src/include/common/hex_decode.h | 16 +++++ src/include/utils/builtins.h | 1 - src/interfaces/ecpg/ecpglib/data.c | 52 +------------- src/tools/msvc/Mkvcbuild.pm | 2 +- 8 files changed, 127 insertions(+), 116 deletions(-) create mode 100644 src/common/hex_decode.c create mode 100644 src/include/common/hex_decode.h diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.c index a609d49c12..a6c65b1657 100644 --- a/src/backend/utils/adt/encode.c +++ b/src/backend/utils/adt/encode.c @@ -15,6 +15,7 @@ #include +#include "common/hex_decode.h" #include "mb/pg_wchar.h" #include "utils/builtins.h" #include "utils/memutils.h" @@ -146,17 +147,6 @@ binary_decode(PG_FUNCTION_ARGS) static const char hextbl[] = "0123456789abcdef"; -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, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -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, 10, 11, 12, 13, 14, 15, -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) { @@ -171,58 +161,6 @@ hex_encode(const char *src, size_t len, char *dst) return (uint64) len * 2; } -static inline char -get_hex(const char *cp) -{ - unsigned char c = (unsigned char) *cp; - int res = -1; - - if (c < 127) - res = hexlookup[c]; - - if (res < 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid hexadecimal digit: \"%.*s\"", - pg_mblen(cp), cp))); - - return (char) res; -} - -uint64 -hex_decode(const char *src, size_t len, char *dst) -{ - 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; - } - v1 = get_hex(s) << 4; - s++; - if (s >= srcend) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid hexadecimal data: odd number of digits"))); - - v2 = get_hex(s); - s++; - *p++ = v1 | v2; - } - - return p - dst; -} - static uint64 hex_enc_len(const char *src, size_t srclen) { diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index ff9bf238f3..9300d19e0c 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -22,6 +22,7 @@ #include "catalog/pg_type.h" #include "common/hashfn.h" #include "common/int.h" +#include "common/hex_decode.h" #include "common/unicode_norm.h" #include "lib/hyperloglog.h" #include "libpq/pqformat.h" diff --git a/src/common/Makefile b/src/common/Makefile index af891cb0ce..f624977939 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -58,6 +58,7 @@ OBJS_COMMON = \ file_perm.o \ file_utils.o \ hashfn.o \ + hex_decode.o \ ip.o \ jsonapi.o \ keywords.o \ diff --git a/src/common/hex_decode.c b/src/common/hex_decode.c new file mode 100644 index 0000000000..3ecdc73b5c --- /dev/null +++ b/src/common/hex_decode.c @@ -0,0 +1,106 @@ +/*------------------------------------------------------------------------- + * + * hex_decode.c + * hex decoding + * + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/common/hex_decode.c + * + *------------------------------------------------------------------------- + */ + + +#ifndef FRONTEND +#include "postgres.h" +#else +#include "postgres_fe.h" +#endif + +#ifdef FRONTEND +#include "common/logging.h" +#else +#include "mb/pg_wchar.h" +#endif +#include "common/hex_decode.h" + + +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, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -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, 10, 11, 12, 13, 14, 15, -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, +}; + +static inline char +get_hex(const char *cp) +{ + unsigned char c = (unsigned char) *cp; + int res = -1; + + if (c < 127) + res = hexlookup[c]; + + if (res < 0) + { +#ifdef FRONTEND + pg_log_fatal("invalid hexadecimal digit"); + exit(EXIT_FAILURE); +#else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid hexadecimal digit: \"%.*s\"", + pg_mblen(cp), cp))); +#endif + } + + return (char) res; +} + +uint64 +hex_decode(const char *src, size_t len, char *dst) +{ + 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; + } + v1 = get_hex(s) << 4; + s++; + if (s >= srcend) + { +#ifdef FRONTEND + pg_log_fatal("invalid hexadecimal data: odd number of digits"); + exit(EXIT_FAILURE); +#else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid hexadecimal data: odd number of digits"))); +#endif + } + v2 = get_hex(s); + s++; + *p++ = v1 | v2; + } + + return p - dst; +} diff --git a/src/include/common/hex_decode.h b/src/include/common/hex_decode.h new file mode 100644 index 0000000000..1f99f069b2 --- /dev/null +++ b/src/include/common/hex_decode.h @@ -0,0 +1,16 @@ +/* + * hex_decode.h + * hex decoding + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/common/hex_decode.h + */ +#ifndef COMMON_HEX_DECODE_H +#define COMMON_HEX_DECODE_H + +extern uint64 hex_decode(const char *src, size_t len, char *dst); + + +#endif /* COMMON_HEX_DECODE_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 4db5ad3f12..19271e0696 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -33,7 +33,6 @@ extern int errdomainconstraint(Oid datatypeOid, const char *conname); /* encode.c */ extern uint64 hex_encode(const char *src, size_t len, char *dst); -extern uint64 hex_decode(const char *src, size_t len, char *dst); /* int.c */ extern int2vector *buildint2vector(const int16 *int2s, int n); diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c index 6bc91ef7eb..326de71cb1 100644 --- a/src/interfaces/ecpg/ecpglib/data.c +++ b/src/interfaces/ecpg/ecpglib/data.c @@ -5,6 +5,7 @@ #include +#include "common/hex_decode.h" #include "ecpgerrno.h" #include "ecpglib.h" #include "ecpglib_extern.h" @@ -136,57 +137,6 @@ ecpg_hex_dec_len(unsigned srclen) return srclen >> 1; } -static inline char -get_hex(char c) -{ - 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, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -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, 10, 11, 12, 13, 14, 15, -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, - }; - int res = -1; - - if (c > 0 && c < 127) - res = hexlookup[(unsigned char) c]; - - return (char) res; -} - -static unsigned -hex_decode(const char *src, unsigned len, char *dst) -{ - 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; - } - v1 = get_hex(*s++) << 4; - if (s >= srcend) - return -1; - - v2 = get_hex(*s++); - *p++ = v1 | v2; - } - - return p - dst; -} - unsigned ecpg_hex_encode(const char *src, unsigned len, char *dst) { diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index f92c14030d..7f014a12c9 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -121,7 +121,7 @@ sub mkvcbuild our @pgcommonallfiles = qw( archive.c base64.c checksum_helper.c config_info.c controldata_utils.c d2s.c encnames.c exec.c - f2s.c file_perm.c file_utils.c hashfn.c ip.c jsonapi.c + f2s.c file_perm.c file_utils.c hashfn.c hex_decode.c ip.c jsonapi.c keywords.c kwlookup.c link-canary.c md5_common.c pg_get_line.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c saslprep.c scram-common.c string.c stringinfo.c unicode_norm.c username.c