On Fri, Dec 25, 2020 at 09:04:41AM +0900, Michael Paquier wrote:
> Looks like the defense put in place by 6b1c5ca has allowed to catch up
> a bug here. When base64 has been copied from encode.c to src/common/
> for SCRAM (newlines should not be handled by SCRAM, hence the copy),
> we have done the same. The copied code just returns -1 for error
> paths. For this case, I think that you should also prefix those
> functions with "pg_", and also include the encode part for
> completeness.
I now understand the wisdom of your suggestion. Attached is a patch
that removes hex_decode from ecpg properly, and returns -1 from the
/common version.
--
Bruce Momjian <[email protected]> https://momjian.us
EnterpriseDB https://enterprisedb.com
The usefulness of a cup is in its emptiness, Bruce Lee
diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.c
new file mode 100644
index a6c65b1..4604e9b
*** a/src/backend/utils/adt/encode.c
--- b/src/backend/utils/adt/encode.c
*************** static const struct
*** 504,510 ****
{
"hex",
{
! hex_enc_len, hex_dec_len, hex_encode, hex_decode
}
},
{
--- 504,510 ----
{
"hex",
{
! hex_enc_len, hex_dec_len, hex_encode, pg_hex_decode
}
},
{
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
new file mode 100644
index 9300d19..60b02aa
*** a/src/backend/utils/adt/varlena.c
--- b/src/backend/utils/adt/varlena.c
*************** byteain(PG_FUNCTION_ARGS)
*** 307,313 ****
bc = (len - 2) / 2 + VARHDRSZ; /* maximum possible length */
result = palloc(bc);
! bc = hex_decode(inputText + 2, len - 2, VARDATA(result));
SET_VARSIZE(result, bc + VARHDRSZ); /* actual length */
PG_RETURN_BYTEA_P(result);
--- 307,313 ----
bc = (len - 2) / 2 + VARHDRSZ; /* maximum possible length */
result = palloc(bc);
! bc = pg_hex_decode(inputText + 2, len - 2, VARDATA(result));
SET_VARSIZE(result, bc + VARHDRSZ); /* actual length */
PG_RETURN_BYTEA_P(result);
diff --git a/src/common/hex_decode.c b/src/common/hex_decode.c
new file mode 100644
index 3ecdc73..ce17812
*** a/src/common/hex_decode.c
--- b/src/common/hex_decode.c
*************** get_hex(const char *cp)
*** 66,72 ****
}
uint64
! hex_decode(const char *src, size_t len, char *dst)
{
const char *s,
*srcend;
--- 66,72 ----
}
uint64
! pg_hex_decode(const char *src, size_t len, char *dst)
{
const char *s,
*srcend;
*************** hex_decode(const char *src, size_t len,
*** 89,96 ****
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),
--- 89,95 ----
if (s >= srcend)
{
#ifdef FRONTEND
! return -1;
#else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
diff --git a/src/include/common/hex_decode.h b/src/include/common/hex_decode.h
new file mode 100644
index 1f99f06..ec210b6
*** a/src/include/common/hex_decode.h
--- b/src/include/common/hex_decode.h
***************
*** 10,16 ****
#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 */
--- 10,16 ----
#ifndef COMMON_HEX_DECODE_H
#define COMMON_HEX_DECODE_H
! extern uint64 pg_hex_decode(const char *src, size_t len, char *dst);
#endif /* COMMON_HEX_DECODE_H */
diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c
new file mode 100644
index 6bc91ef..0bb43f1
*** a/src/interfaces/ecpg/ecpglib/data.c
--- b/src/interfaces/ecpg/ecpglib/data.c
***************
*** 5,10 ****
--- 5,11 ----
#include <math.h>
+ #include "common/hex_decode.h"
#include "ecpgerrno.h"
#include "ecpglib.h"
#include "ecpglib_extern.h"
*************** ecpg_hex_dec_len(unsigned srclen)
*** 136,192 ****
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)
{
--- 137,142 ----
*************** ecpg_get_data(const PGresult *results, i
*** 532,538 ****
dst_size = ecpg_hex_enc_len(varcharsize);
src_size = size - 2; /* exclude backslash + 'x' */
dec_size = src_size < dst_size ? src_size : dst_size;
! variable->len = hex_decode(pval + 2, dec_size, variable->arr);
if (dst_size < src_size)
{
--- 482,488 ----
dst_size = ecpg_hex_enc_len(varcharsize);
src_size = size - 2; /* exclude backslash + 'x' */
dec_size = src_size < dst_size ? src_size : dst_size;
! variable->len = pg_hex_decode(pval + 2, dec_size, variable->arr);
if (dst_size < src_size)
{