Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7a05425

Browse filesBrowse 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
Copy full SHA for 7a05425

File tree

4 files changed

+137
-50
lines changed
Filter options

4 files changed

+137
-50
lines changed

‎contrib/ltree/expected/ltree.out

Copy file name to clipboardExpand all lines: contrib/ltree/expected/ltree.out
+25Lines 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

Copy file name to clipboardExpand all lines: contrib/ltree/ltree_io.c
+45-27Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.