Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7a05425

Browse files
committed
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
1 parent 3b76622 commit 7a05425

File tree

4 files changed

+137
-50
lines changed

4 files changed

+137
-50
lines changed

contrib/ltree/expected/ltree.out

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8084,3 +8084,28 @@ SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;
80848084
15
80858085
(1 row)
80868086

8087+
-- test non-error-throwing input
8088+
SELECT str as "value", typ as "type",
8089+
pg_input_is_valid(str,typ) as ok,
8090+
pg_input_error_message(str,typ) as errmsg
8091+
FROM (VALUES ('.2.3', 'ltree'),
8092+
('1.2.', 'ltree'),
8093+
('1.2.3','ltree'),
8094+
('@.2.3','lquery'),
8095+
(' 2.3', 'lquery'),
8096+
('1.2.3','lquery'),
8097+
('$tree & aWdf@*','ltxtquery'),
8098+
('!tree & aWdf@*','ltxtquery'))
8099+
AS a(str,typ);
8100+
value | type | ok | errmsg
8101+
----------------+-----------+----+------------------------------------
8102+
.2.3 | ltree | f | ltree syntax error at character 1
8103+
1.2. | ltree | f | ltree syntax error
8104+
1.2.3 | ltree | t |
8105+
@.2.3 | lquery | f | lquery syntax error at character 1
8106+
2.3 | lquery | f | lquery syntax error at character 1
8107+
1.2.3 | lquery | t |
8108+
$tree & aWdf@* | ltxtquery | f | operand syntax error
8109+
!tree & aWdf@* | ltxtquery | t |
8110+
(8 rows)
8111+

contrib/ltree/ltree_io.c

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ typedef struct
2424
#define LTPRS_WAITNAME 0
2525
#define LTPRS_WAITDELIM 1
2626

27-
static void finish_nodeitem(nodeitem *lptr, const char *ptr,
28-
bool is_lquery, int pos);
27+
static bool finish_nodeitem(nodeitem *lptr, const char *ptr,
28+
bool is_lquery, int pos, struct Node *escontext);
2929

3030

3131
/*
3232
* expects a null terminated string
3333
* returns an ltree
3434
*/
3535
static ltree *
36-
parse_ltree(const char *buf)
36+
parse_ltree(const char *buf, struct Node *escontext)
3737
{
3838
const char *ptr;
3939
nodeitem *list,
@@ -46,7 +46,7 @@ parse_ltree(const char *buf)
4646
int charlen;
4747
int pos = 1; /* character position for error messages */
4848

49-
#define UNCHAR ereport(ERROR, \
49+
#define UNCHAR ereturn(escontext, NULL,\
5050
errcode(ERRCODE_SYNTAX_ERROR), \
5151
errmsg("ltree syntax error at character %d", \
5252
pos))
@@ -61,7 +61,7 @@ parse_ltree(const char *buf)
6161
}
6262

6363
if (num + 1 > LTREE_MAX_LEVELS)
64-
ereport(ERROR,
64+
ereturn(escontext, NULL,
6565
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
6666
errmsg("number of ltree labels (%d) exceeds the maximum allowed (%d)",
6767
num + 1, LTREE_MAX_LEVELS)));
@@ -86,7 +86,8 @@ parse_ltree(const char *buf)
8686
case LTPRS_WAITDELIM:
8787
if (t_iseq(ptr, '.'))
8888
{
89-
finish_nodeitem(lptr, ptr, false, pos);
89+
if (!finish_nodeitem(lptr, ptr, false, pos, escontext))
90+
return NULL;
9091
totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
9192
lptr++;
9293
state = LTPRS_WAITNAME;
@@ -105,12 +106,13 @@ parse_ltree(const char *buf)
105106

106107
if (state == LTPRS_WAITDELIM)
107108
{
108-
finish_nodeitem(lptr, ptr, false, pos);
109+
if (!finish_nodeitem(lptr, ptr, false, pos, escontext))
110+
return NULL;
109111
totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
110112
lptr++;
111113
}
112114
else if (!(state == LTPRS_WAITNAME && lptr == list))
113-
ereport(ERROR,
115+
ereturn(escontext, NULL,
114116
(errcode(ERRCODE_SYNTAX_ERROR),
115117
errmsg("ltree syntax error"),
116118
errdetail("Unexpected end of input.")));
@@ -172,8 +174,12 @@ Datum
172174
ltree_in(PG_FUNCTION_ARGS)
173175
{
174176
char *buf = (char *) PG_GETARG_POINTER(0);
177+
ltree *res;
175178

176-
PG_RETURN_POINTER(parse_ltree(buf));
179+
if ((res = parse_ltree(buf, fcinfo->context)) == NULL)
180+
PG_RETURN_NULL();
181+
182+
PG_RETURN_POINTER(res);
177183
}
178184

179185
PG_FUNCTION_INFO_V1(ltree_out);
@@ -232,7 +238,7 @@ ltree_recv(PG_FUNCTION_ARGS)
232238
elog(ERROR, "unsupported ltree version number %d", version);
233239

234240
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
235-
res = parse_ltree(str);
241+
res = parse_ltree(str, NULL);
236242
pfree(str);
237243

238244
PG_RETURN_POINTER(res);
@@ -259,7 +265,7 @@ ltree_recv(PG_FUNCTION_ARGS)
259265
* returns an lquery
260266
*/
261267
static lquery *
262-
parse_lquery(const char *buf)
268+
parse_lquery(const char *buf, struct Node *escontext)
263269
{
264270
const char *ptr;
265271
int num = 0,
@@ -277,7 +283,7 @@ parse_lquery(const char *buf)
277283
int charlen;
278284
int pos = 1; /* character position for error messages */
279285

280-
#define UNCHAR ereport(ERROR, \
286+
#define UNCHAR ereturn(escontext, NULL,\
281287
errcode(ERRCODE_SYNTAX_ERROR), \
282288
errmsg("lquery syntax error at character %d", \
283289
pos))
@@ -297,7 +303,7 @@ parse_lquery(const char *buf)
297303

298304
num++;
299305
if (num > LQUERY_MAX_LEVELS)
300-
ereport(ERROR,
306+
ereturn(escontext, NULL,
301307
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
302308
errmsg("number of lquery items (%d) exceeds the maximum allowed (%d)",
303309
num, LQUERY_MAX_LEVELS)));
@@ -361,18 +367,21 @@ parse_lquery(const char *buf)
361367
}
362368
else if (t_iseq(ptr, '|'))
363369
{
364-
finish_nodeitem(lptr, ptr, true, pos);
370+
if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
371+
return NULL;
365372
state = LQPRS_WAITVAR;
366373
}
367374
else if (t_iseq(ptr, '{'))
368375
{
369-
finish_nodeitem(lptr, ptr, true, pos);
376+
if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
377+
return NULL;
370378
curqlevel->flag |= LQL_COUNT;
371379
state = LQPRS_WAITFNUM;
372380
}
373381
else if (t_iseq(ptr, '.'))
374382
{
375-
finish_nodeitem(lptr, ptr, true, pos);
383+
if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
384+
return NULL;
376385
state = LQPRS_WAITLEVEL;
377386
curqlevel = NEXTLEV(curqlevel);
378387
}
@@ -407,7 +416,7 @@ parse_lquery(const char *buf)
407416
int low = atoi(ptr);
408417

409418
if (low < 0 || low > LTREE_MAX_LEVELS)
410-
ereport(ERROR,
419+
ereturn(escontext, NULL,
411420
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
412421
errmsg("lquery syntax error"),
413422
errdetail("Low limit (%d) exceeds the maximum allowed (%d), at character %d.",
@@ -425,13 +434,13 @@ parse_lquery(const char *buf)
425434
int high = atoi(ptr);
426435

427436
if (high < 0 || high > LTREE_MAX_LEVELS)
428-
ereport(ERROR,
437+
ereturn(escontext, NULL,
429438
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
430439
errmsg("lquery syntax error"),
431440
errdetail("High limit (%d) exceeds the maximum allowed (%d), at character %d.",
432441
high, LTREE_MAX_LEVELS, pos)));
433442
else if (curqlevel->low > high)
434-
ereport(ERROR,
443+
ereturn(escontext, NULL,
435444
(errcode(ERRCODE_SYNTAX_ERROR),
436445
errmsg("lquery syntax error"),
437446
errdetail("Low limit (%d) is greater than high limit (%d), at character %d.",
@@ -485,11 +494,14 @@ parse_lquery(const char *buf)
485494
}
486495

487496
if (state == LQPRS_WAITDELIM)
488-
finish_nodeitem(lptr, ptr, true, pos);
497+
{
498+
if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
499+
return false;
500+
}
489501
else if (state == LQPRS_WAITOPEN)
490502
curqlevel->high = LTREE_MAX_LEVELS;
491503
else if (state != LQPRS_WAITEND)
492-
ereport(ERROR,
504+
ereturn(escontext, NULL,
493505
(errcode(ERRCODE_SYNTAX_ERROR),
494506
errmsg("lquery syntax error"),
495507
errdetail("Unexpected end of input.")));
@@ -569,8 +581,9 @@ parse_lquery(const char *buf)
569581
* Close out parsing an ltree or lquery nodeitem:
570582
* compute the correct length, and complain if it's not OK
571583
*/
572-
static void
573-
finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos)
584+
static bool
585+
finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos,
586+
struct Node *escontext)
574587
{
575588
if (is_lquery)
576589
{
@@ -591,18 +604,19 @@ finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos)
591604

592605
/* Complain if it's empty or too long */
593606
if (lptr->len == 0)
594-
ereport(ERROR,
607+
ereturn(escontext, false,
595608
(errcode(ERRCODE_SYNTAX_ERROR),
596609
is_lquery ?
597610
errmsg("lquery syntax error at character %d", pos) :
598611
errmsg("ltree syntax error at character %d", pos),
599612
errdetail("Empty labels are not allowed.")));
600613
if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
601-
ereport(ERROR,
614+
ereturn(escontext, false,
602615
(errcode(ERRCODE_NAME_TOO_LONG),
603616
errmsg("label string is too long"),
604617
errdetail("Label length is %d, must be at most %d, at character %d.",
605618
lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
619+
return true;
606620
}
607621

608622
/*
@@ -730,8 +744,12 @@ Datum
730744
lquery_in(PG_FUNCTION_ARGS)
731745
{
732746
char *buf = (char *) PG_GETARG_POINTER(0);
747+
lquery *res;
748+
749+
if ((res = parse_lquery(buf, fcinfo->context)) == NULL)
750+
PG_RETURN_NULL();
733751

734-
PG_RETURN_POINTER(parse_lquery(buf));
752+
PG_RETURN_POINTER(res);
735753
}
736754

737755
PG_FUNCTION_INFO_V1(lquery_out);
@@ -790,7 +808,7 @@ lquery_recv(PG_FUNCTION_ARGS)
790808
elog(ERROR, "unsupported lquery version number %d", version);
791809

792810
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
793-
res = parse_lquery(str);
811+
res = parse_lquery(str, NULL);
794812
pfree(str);
795813

796814
PG_RETURN_POINTER(res);

0 commit comments

Comments
 (0)