PostgreSQL Source Code  git master
hex.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * hex.c
4  * Encoding and decoding routines for hex.
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  * src/common/hex.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 
16 #ifndef FRONTEND
17 #include "postgres.h"
18 #else
19 #include "postgres_fe.h"
20 #endif
21 
22 #include "common/hex.h"
23 #ifdef FRONTEND
24 #include "common/logging.h"
25 #endif
26 #include "mb/pg_wchar.h"
27 
28 
29 static const int8 hexlookup[128] = {
30  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
32  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
34  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
37  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
38 };
39 
40 static const char hextbl[] = "0123456789abcdef";
41 
42 static inline char
43 get_hex(const char *cp)
44 {
45  unsigned char c = (unsigned char) *cp;
46  int res = -1;
47 
48  if (c < 127)
49  res = hexlookup[c];
50 
51  if (res < 0)
52  {
53 #ifdef FRONTEND
54  pg_log_fatal("invalid hexadecimal digit");
55  exit(EXIT_FAILURE);
56 #else
57  ereport(ERROR,
58  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
59  errmsg("invalid hexadecimal digit: \"%.*s\"",
60  pg_mblen(cp), cp)));
61 #endif
62  }
63 
64  return (char) res;
65 }
66 
67 /*
68  * pg_hex_encode
69  *
70  * Encode into hex the given string. Returns the length of the encoded
71  * string.
72  */
73 uint64
74 pg_hex_encode(const char *src, size_t srclen, char *dst, size_t dstlen)
75 {
76  const char *end = src + srclen;
77  char *p;
78 
79  p = dst;
80 
81  while (src < end)
82  {
83  /*
84  * Leave if there is an overflow in the area allocated for the encoded
85  * string.
86  */
87  if ((p - dst + 2) > dstlen)
88  {
89 #ifdef FRONTEND
90  pg_log_fatal("overflow of destination buffer in hex encoding");
91  exit(EXIT_FAILURE);
92 #else
93  elog(ERROR, "overflow of destination buffer in hex encoding");
94 #endif
95  }
96 
97  *p++ = hextbl[(*src >> 4) & 0xF];
98  *p++ = hextbl[*src & 0xF];
99  src++;
100  }
101 
102  Assert((p - dst) <= dstlen);
103  return p - dst;
104 }
105 
106 /*
107  * pg_hex_decode
108  *
109  * Decode the given hex string. Returns the length of the decoded string.
110  */
111 uint64
112 pg_hex_decode(const char *src, size_t srclen, char *dst, size_t dstlen)
113 {
114  const char *s,
115  *srcend;
116  char v1,
117  v2,
118  *p;
119 
120  srcend = src + srclen;
121  s = src;
122  p = dst;
123  while (s < srcend)
124  {
125  if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
126  {
127  s++;
128  continue;
129  }
130  v1 = get_hex(s) << 4;
131  s++;
132 
133  if (s >= srcend)
134  {
135 #ifdef FRONTEND
136  pg_log_fatal("invalid hexadecimal data: odd number of digits");
137  exit(EXIT_FAILURE);
138 #else
139  ereport(ERROR,
140  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
141  errmsg("invalid hexadecimal data: odd number of digits")));
142 #endif
143  }
144 
145  v2 = get_hex(s);
146  s++;
147 
148  /* overflow check */
149  if ((p - dst + 1) > dstlen)
150  {
151 #ifdef FRONTEND
152  pg_log_fatal("overflow of destination buffer in hex decoding");
153  exit(EXIT_FAILURE);
154 #else
155  elog(ERROR, "overflow of destination buffer in hex decoding");
156 #endif
157  }
158 
159  *p++ = v1 | v2;
160  }
161 
162  Assert((p - dst) <= dstlen);
163  return p - dst;
164 }
165 
166 /*
167  * pg_hex_enc_len
168  *
169  * Returns to caller the length of the string if it were encoded with
170  * hex based on the length provided by caller. This is useful to estimate
171  * how large a buffer allocation needs to be done before doing the actual
172  * encoding.
173  */
174 uint64
175 pg_hex_enc_len(size_t srclen)
176 {
177  return (uint64) srclen << 1;
178 }
179 
180 /*
181  * pg_hex_dec_len
182  *
183  * Returns to caller the length of the string if it were to be decoded
184  * with hex, based on the length given by caller. This is useful to
185  * estimate how large a buffer allocation needs to be done before doing
186  * the actual decoding.
187  */
188 uint64
189 pg_hex_dec_len(size_t srclen)
190 {
191  return (uint64) srclen >> 1;
192 }
static char get_hex(const char *cp)
Definition: hex.c:43
uint64 pg_hex_enc_len(size_t srclen)
Definition: hex.c:175
int errcode(int sqlerrcode)
Definition: elog.c:698
uint64 pg_hex_dec_len(size_t srclen)
Definition: hex.c:189
#define ERROR
Definition: elog.h:46
char * c
uint64 pg_hex_encode(const char *src, size_t srclen, char *dst, size_t dstlen)
Definition: hex.c:74
signed char int8
Definition: c.h:427
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
uint64 pg_hex_decode(const char *src, size_t srclen, char *dst, size_t dstlen)
Definition: hex.c:112
int pg_mblen(const char *mbstr)
Definition: mbutils.c:966
static const int8 hexlookup[128]
Definition: hex.c:29
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define EXIT_FAILURE
Definition: settings.h:162
static const char hextbl[]
Definition: hex.c:40
#define pg_log_fatal(...)
Definition: logging.h:76