mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Convert contrib/ltree's input functions to report errors softly
Reviewed by Tom Lane and Amul Sul Discussion: https://postgr.es/m/49e598c2-cfe8-0928-b6fb-d0cc51aab626@dunslane.net
This commit is contained in:
@ -24,8 +24,8 @@ typedef struct
|
||||
#define LTPRS_WAITNAME 0
|
||||
#define LTPRS_WAITDELIM 1
|
||||
|
||||
static void finish_nodeitem(nodeitem *lptr, const char *ptr,
|
||||
bool is_lquery, int pos);
|
||||
static bool finish_nodeitem(nodeitem *lptr, const char *ptr,
|
||||
bool is_lquery, int pos, struct Node *escontext);
|
||||
|
||||
|
||||
/*
|
||||
@ -33,7 +33,7 @@ static void finish_nodeitem(nodeitem *lptr, const char *ptr,
|
||||
* returns an ltree
|
||||
*/
|
||||
static ltree *
|
||||
parse_ltree(const char *buf)
|
||||
parse_ltree(const char *buf, struct Node *escontext)
|
||||
{
|
||||
const char *ptr;
|
||||
nodeitem *list,
|
||||
@ -46,7 +46,7 @@ parse_ltree(const char *buf)
|
||||
int charlen;
|
||||
int pos = 1; /* character position for error messages */
|
||||
|
||||
#define UNCHAR ereport(ERROR, \
|
||||
#define UNCHAR ereturn(escontext, NULL,\
|
||||
errcode(ERRCODE_SYNTAX_ERROR), \
|
||||
errmsg("ltree syntax error at character %d", \
|
||||
pos))
|
||||
@ -61,7 +61,7 @@ parse_ltree(const char *buf)
|
||||
}
|
||||
|
||||
if (num + 1 > LTREE_MAX_LEVELS)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, NULL,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("number of ltree labels (%d) exceeds the maximum allowed (%d)",
|
||||
num + 1, LTREE_MAX_LEVELS)));
|
||||
@ -86,7 +86,8 @@ parse_ltree(const char *buf)
|
||||
case LTPRS_WAITDELIM:
|
||||
if (t_iseq(ptr, '.'))
|
||||
{
|
||||
finish_nodeitem(lptr, ptr, false, pos);
|
||||
if (!finish_nodeitem(lptr, ptr, false, pos, escontext))
|
||||
return NULL;
|
||||
totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
|
||||
lptr++;
|
||||
state = LTPRS_WAITNAME;
|
||||
@ -105,12 +106,13 @@ parse_ltree(const char *buf)
|
||||
|
||||
if (state == LTPRS_WAITDELIM)
|
||||
{
|
||||
finish_nodeitem(lptr, ptr, false, pos);
|
||||
if (!finish_nodeitem(lptr, ptr, false, pos, escontext))
|
||||
return NULL;
|
||||
totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
|
||||
lptr++;
|
||||
}
|
||||
else if (!(state == LTPRS_WAITNAME && lptr == list))
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, NULL,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("ltree syntax error"),
|
||||
errdetail("Unexpected end of input.")));
|
||||
@ -172,8 +174,12 @@ Datum
|
||||
ltree_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *buf = (char *) PG_GETARG_POINTER(0);
|
||||
ltree *res;
|
||||
|
||||
PG_RETURN_POINTER(parse_ltree(buf));
|
||||
if ((res = parse_ltree(buf, fcinfo->context)) == NULL)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
PG_RETURN_POINTER(res);
|
||||
}
|
||||
|
||||
PG_FUNCTION_INFO_V1(ltree_out);
|
||||
@ -232,7 +238,7 @@ ltree_recv(PG_FUNCTION_ARGS)
|
||||
elog(ERROR, "unsupported ltree version number %d", version);
|
||||
|
||||
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
|
||||
res = parse_ltree(str);
|
||||
res = parse_ltree(str, NULL);
|
||||
pfree(str);
|
||||
|
||||
PG_RETURN_POINTER(res);
|
||||
@ -259,7 +265,7 @@ ltree_recv(PG_FUNCTION_ARGS)
|
||||
* returns an lquery
|
||||
*/
|
||||
static lquery *
|
||||
parse_lquery(const char *buf)
|
||||
parse_lquery(const char *buf, struct Node *escontext)
|
||||
{
|
||||
const char *ptr;
|
||||
int num = 0,
|
||||
@ -277,7 +283,7 @@ parse_lquery(const char *buf)
|
||||
int charlen;
|
||||
int pos = 1; /* character position for error messages */
|
||||
|
||||
#define UNCHAR ereport(ERROR, \
|
||||
#define UNCHAR ereturn(escontext, NULL,\
|
||||
errcode(ERRCODE_SYNTAX_ERROR), \
|
||||
errmsg("lquery syntax error at character %d", \
|
||||
pos))
|
||||
@ -297,7 +303,7 @@ parse_lquery(const char *buf)
|
||||
|
||||
num++;
|
||||
if (num > LQUERY_MAX_LEVELS)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, NULL,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("number of lquery items (%d) exceeds the maximum allowed (%d)",
|
||||
num, LQUERY_MAX_LEVELS)));
|
||||
@ -361,18 +367,21 @@ parse_lquery(const char *buf)
|
||||
}
|
||||
else if (t_iseq(ptr, '|'))
|
||||
{
|
||||
finish_nodeitem(lptr, ptr, true, pos);
|
||||
if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
|
||||
return NULL;
|
||||
state = LQPRS_WAITVAR;
|
||||
}
|
||||
else if (t_iseq(ptr, '{'))
|
||||
{
|
||||
finish_nodeitem(lptr, ptr, true, pos);
|
||||
if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
|
||||
return NULL;
|
||||
curqlevel->flag |= LQL_COUNT;
|
||||
state = LQPRS_WAITFNUM;
|
||||
}
|
||||
else if (t_iseq(ptr, '.'))
|
||||
{
|
||||
finish_nodeitem(lptr, ptr, true, pos);
|
||||
if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
|
||||
return NULL;
|
||||
state = LQPRS_WAITLEVEL;
|
||||
curqlevel = NEXTLEV(curqlevel);
|
||||
}
|
||||
@ -407,7 +416,7 @@ parse_lquery(const char *buf)
|
||||
int low = atoi(ptr);
|
||||
|
||||
if (low < 0 || low > LTREE_MAX_LEVELS)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, NULL,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("lquery syntax error"),
|
||||
errdetail("Low limit (%d) exceeds the maximum allowed (%d), at character %d.",
|
||||
@ -425,13 +434,13 @@ parse_lquery(const char *buf)
|
||||
int high = atoi(ptr);
|
||||
|
||||
if (high < 0 || high > LTREE_MAX_LEVELS)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, NULL,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("lquery syntax error"),
|
||||
errdetail("High limit (%d) exceeds the maximum allowed (%d), at character %d.",
|
||||
high, LTREE_MAX_LEVELS, pos)));
|
||||
else if (curqlevel->low > high)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, NULL,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("lquery syntax error"),
|
||||
errdetail("Low limit (%d) is greater than high limit (%d), at character %d.",
|
||||
@ -485,11 +494,14 @@ parse_lquery(const char *buf)
|
||||
}
|
||||
|
||||
if (state == LQPRS_WAITDELIM)
|
||||
finish_nodeitem(lptr, ptr, true, pos);
|
||||
{
|
||||
if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
|
||||
return false;
|
||||
}
|
||||
else if (state == LQPRS_WAITOPEN)
|
||||
curqlevel->high = LTREE_MAX_LEVELS;
|
||||
else if (state != LQPRS_WAITEND)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, NULL,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("lquery syntax error"),
|
||||
errdetail("Unexpected end of input.")));
|
||||
@ -569,8 +581,9 @@ parse_lquery(const char *buf)
|
||||
* Close out parsing an ltree or lquery nodeitem:
|
||||
* compute the correct length, and complain if it's not OK
|
||||
*/
|
||||
static void
|
||||
finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos)
|
||||
static bool
|
||||
finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos,
|
||||
struct Node *escontext)
|
||||
{
|
||||
if (is_lquery)
|
||||
{
|
||||
@ -591,18 +604,19 @@ finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos)
|
||||
|
||||
/* Complain if it's empty or too long */
|
||||
if (lptr->len == 0)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, false,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
is_lquery ?
|
||||
errmsg("lquery syntax error at character %d", pos) :
|
||||
errmsg("ltree syntax error at character %d", pos),
|
||||
errdetail("Empty labels are not allowed.")));
|
||||
if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, false,
|
||||
(errcode(ERRCODE_NAME_TOO_LONG),
|
||||
errmsg("label string is too long"),
|
||||
errdetail("Label length is %d, must be at most %d, at character %d.",
|
||||
lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -730,8 +744,12 @@ Datum
|
||||
lquery_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *buf = (char *) PG_GETARG_POINTER(0);
|
||||
lquery *res;
|
||||
|
||||
PG_RETURN_POINTER(parse_lquery(buf));
|
||||
if ((res = parse_lquery(buf, fcinfo->context)) == NULL)
|
||||
PG_RETURN_NULL();
|
||||
|
||||
PG_RETURN_POINTER(res);
|
||||
}
|
||||
|
||||
PG_FUNCTION_INFO_V1(lquery_out);
|
||||
@ -790,7 +808,7 @@ lquery_recv(PG_FUNCTION_ARGS)
|
||||
elog(ERROR, "unsupported lquery version number %d", version);
|
||||
|
||||
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
|
||||
res = parse_lquery(str);
|
||||
res = parse_lquery(str, NULL);
|
||||
pfree(str);
|
||||
|
||||
PG_RETURN_POINTER(res);
|
||||
|
Reference in New Issue
Block a user