/*------------------------------------------------------------------------- * * 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; }