diff options
Diffstat (limited to 'src/backend/utils/adt/encode.c')
-rw-r--r-- | src/backend/utils/adt/encode.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.c index feb3e830e4f..f3bb5cca43c 100644 --- a/src/backend/utils/adt/encode.c +++ b/src/backend/utils/adt/encode.c @@ -171,8 +171,8 @@ hex_encode(const char *src, size_t len, char *dst) return (uint64) len * 2; } -static inline char -get_hex(const char *cp) +static inline bool +get_hex(const char *cp, char *out) { unsigned char c = (unsigned char) *cp; int res = -1; @@ -180,18 +180,20 @@ get_hex(const char *cp) 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))); + *out = (char) res; - return (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, @@ -208,16 +210,23 @@ hex_decode(const char *src, size_t len, char *dst) s++; continue; } - v1 = get_hex(s) << 4; + if (!get_hex(s, &v1)) + ereturn(escontext, 0, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid hexadecimal digit: \"%.*s\"", + pg_mblen(s), s))); s++; if (s >= srcend) - ereport(ERROR, + ereturn(escontext, 0, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid hexadecimal data: odd number of digits"))); - - v2 = get_hex(s); + if (!get_hex(s, &v2)) + ereturn(escontext, 0, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid hexadecimal digit: \"%.*s\"", + pg_mblen(s), s))); s++; - *p++ = v1 | v2; + *p++ = (v1 << 4) | v2; } return p - dst; |