1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-22 17:42:17 +03:00

Convert a few more datatype input functions to report errors softly.

Convert the remaining string-category input functions
(bpcharin, varcharin, byteain) to the new style.

Discussion: https://postgr.es/m/3038346.1671060258@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2022-12-14 19:42:05 -05:00
parent 90161dad4d
commit 3b9d2deb67
14 changed files with 203 additions and 30 deletions

View File

@@ -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,17 +180,19 @@ 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;
@@ -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;

View File

@@ -122,9 +122,13 @@ anychar_typmodout(int32 typmod)
*
* If the input string is too long, raise an error, unless the extra
* characters are spaces, in which case they're truncated. (per SQL)
*
* If escontext points to an ErrorSaveContext node, that is filled instead
* of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
* to detect errors.
*/
static BpChar *
bpchar_input(const char *s, size_t len, int32 atttypmod)
bpchar_input(const char *s, size_t len, int32 atttypmod, Node *escontext)
{
BpChar *result;
char *r;
@@ -153,7 +157,7 @@ bpchar_input(const char *s, size_t len, int32 atttypmod)
for (j = mbmaxlen; j < len; j++)
{
if (s[j] != ' ')
ereport(ERROR,
ereturn(escontext, NULL,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("value too long for type character(%d)",
(int) maxlen)));
@@ -195,14 +199,13 @@ Datum
bpcharin(PG_FUNCTION_ARGS)
{
char *s = PG_GETARG_CSTRING(0);
#ifdef NOT_USED
Oid typelem = PG_GETARG_OID(1);
#endif
int32 atttypmod = PG_GETARG_INT32(2);
BpChar *result;
result = bpchar_input(s, strlen(s), atttypmod);
result = bpchar_input(s, strlen(s), atttypmod, fcinfo->context);
PG_RETURN_BPCHAR_P(result);
}
@@ -228,7 +231,6 @@ Datum
bpcharrecv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
#ifdef NOT_USED
Oid typelem = PG_GETARG_OID(1);
#endif
@@ -238,7 +240,7 @@ bpcharrecv(PG_FUNCTION_ARGS)
int nbytes;
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
result = bpchar_input(str, nbytes, atttypmod);
result = bpchar_input(str, nbytes, atttypmod, NULL);
pfree(str);
PG_RETURN_BPCHAR_P(result);
}
@@ -448,11 +450,12 @@ bpchartypmodout(PG_FUNCTION_ARGS)
* If the input string is too long, raise an error, unless the extra
* characters are spaces, in which case they're truncated. (per SQL)
*
* Uses the C string to text conversion function, which is only appropriate
* if VarChar and text are equivalent types.
* If escontext points to an ErrorSaveContext node, that is filled instead
* of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
* to detect errors.
*/
static VarChar *
varchar_input(const char *s, size_t len, int32 atttypmod)
varchar_input(const char *s, size_t len, int32 atttypmod, Node *escontext)
{
VarChar *result;
size_t maxlen;
@@ -468,7 +471,7 @@ varchar_input(const char *s, size_t len, int32 atttypmod)
for (j = mbmaxlen; j < len; j++)
{
if (s[j] != ' ')
ereport(ERROR,
ereturn(escontext, NULL,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("value too long for type character varying(%d)",
(int) maxlen)));
@@ -477,6 +480,10 @@ varchar_input(const char *s, size_t len, int32 atttypmod)
len = mbmaxlen;
}
/*
* We can use cstring_to_text_with_len because VarChar and text are
* binary-compatible types.
*/
result = (VarChar *) cstring_to_text_with_len(s, len);
return result;
}
@@ -489,14 +496,13 @@ Datum
varcharin(PG_FUNCTION_ARGS)
{
char *s = PG_GETARG_CSTRING(0);
#ifdef NOT_USED
Oid typelem = PG_GETARG_OID(1);
#endif
int32 atttypmod = PG_GETARG_INT32(2);
VarChar *result;
result = varchar_input(s, strlen(s), atttypmod);
result = varchar_input(s, strlen(s), atttypmod, fcinfo->context);
PG_RETURN_VARCHAR_P(result);
}
@@ -522,7 +528,6 @@ Datum
varcharrecv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
#ifdef NOT_USED
Oid typelem = PG_GETARG_OID(1);
#endif
@@ -532,7 +537,7 @@ varcharrecv(PG_FUNCTION_ARGS)
int nbytes;
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
result = varchar_input(str, nbytes, atttypmod);
result = varchar_input(str, nbytes, atttypmod, NULL);
pfree(str);
PG_RETURN_VARCHAR_P(result);
}

View File

@@ -295,6 +295,7 @@ Datum
byteain(PG_FUNCTION_ARGS)
{
char *inputText = PG_GETARG_CSTRING(0);
Node *escontext = fcinfo->context;
char *tp;
char *rp;
int bc;
@@ -307,7 +308,8 @@ byteain(PG_FUNCTION_ARGS)
bc = (len - 2) / 2 + VARHDRSZ; /* maximum possible length */
result = palloc(bc);
bc = hex_decode(inputText + 2, len - 2, VARDATA(result));
bc = hex_decode_safe(inputText + 2, len - 2, VARDATA(result),
escontext);
SET_VARSIZE(result, bc + VARHDRSZ); /* actual length */
PG_RETURN_BYTEA_P(result);
@@ -331,7 +333,7 @@ byteain(PG_FUNCTION_ARGS)
/*
* one backslash, not followed by another or ### valid octal
*/
ereport(ERROR,
ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s", "bytea")));
}
@@ -372,7 +374,7 @@ byteain(PG_FUNCTION_ARGS)
/*
* We should never get here. The first pass should not allow it.
*/
ereport(ERROR,
ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s", "bytea")));
}