Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commite37fe1d

Browse files
committed
Convert jsonpath's input function to report errors softly
Reviewed by Tom LaneDiscussion:https://postgr.es/m/a8dc5700-c341-3ba8-0507-cc09881e6200@dunslane.net
1 parent780ec9f commite37fe1d

File tree

8 files changed

+322
-125
lines changed

8 files changed

+322
-125
lines changed

‎src/backend/utils/adt/jsonpath.c

Lines changed: 74 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,19 @@
6666
#include"funcapi.h"
6767
#include"lib/stringinfo.h"
6868
#include"libpq/pqformat.h"
69+
#include"nodes/miscnodes.h"
6970
#include"miscadmin.h"
7071
#include"utils/builtins.h"
7172
#include"utils/json.h"
7273
#include"utils/jsonpath.h"
7374

7475

75-
staticDatumjsonPathFromCstring(char*in,intlen);
76+
staticDatumjsonPathFromCstring(char*in,intlen,structNode*escontext);
7677
staticchar*jsonPathToCstring(StringInfoout,JsonPath*in,
7778
intestimated_len);
78-
staticintflattenJsonPathParseItem(StringInfobuf,JsonPathParseItem*item,
79+
staticboolflattenJsonPathParseItem(StringInfobuf,int*result,
80+
structNode*escontext,
81+
JsonPathParseItem*item,
7982
intnestingLevel,boolinsideArraySubscript);
8083
staticvoidalignStringInfoInt(StringInfobuf);
8184
staticint32reserveSpaceForItemPointer(StringInfobuf);
@@ -95,7 +98,7 @@ jsonpath_in(PG_FUNCTION_ARGS)
9598
char*in=PG_GETARG_CSTRING(0);
9699
intlen=strlen(in);
97100

98-
returnjsonPathFromCstring(in,len);
101+
returnjsonPathFromCstring(in,len,fcinfo->context);
99102
}
100103

101104
/*
@@ -119,7 +122,7 @@ jsonpath_recv(PG_FUNCTION_ARGS)
119122
else
120123
elog(ERROR,"unsupported jsonpath version number: %d",version);
121124

122-
returnjsonPathFromCstring(str,nbytes);
125+
returnjsonPathFromCstring(str,nbytes,NULL);
123126
}
124127

125128
/*
@@ -165,24 +168,29 @@ jsonpath_send(PG_FUNCTION_ARGS)
165168
* representation of jsonpath.
166169
*/
167170
staticDatum
168-
jsonPathFromCstring(char*in,intlen)
171+
jsonPathFromCstring(char*in,intlen,structNode*escontext)
169172
{
170-
JsonPathParseResult*jsonpath=parsejsonpath(in,len);
173+
JsonPathParseResult*jsonpath=parsejsonpath(in,len,escontext);
171174
JsonPath*res;
172175
StringInfoDatabuf;
173176

174-
initStringInfo(&buf);
175-
enlargeStringInfo(&buf,4*len/* estimation */ );
176-
177-
appendStringInfoSpaces(&buf,JSONPATH_HDRSZ);
177+
if (SOFT_ERROR_OCCURRED(escontext))
178+
return (Datum)0;
178179

179180
if (!jsonpath)
180-
ereport(ERROR,
181+
ereturn(escontext, (Datum)0,
181182
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
182183
errmsg("invalid input syntax for type %s: \"%s\"","jsonpath",
183184
in)));
184185

185-
flattenJsonPathParseItem(&buf,jsonpath->expr,0, false);
186+
initStringInfo(&buf);
187+
enlargeStringInfo(&buf,4*len/* estimation */ );
188+
189+
appendStringInfoSpaces(&buf,JSONPATH_HDRSZ);
190+
191+
if (!flattenJsonPathParseItem(&buf,NULL,escontext,
192+
jsonpath->expr,0, false))
193+
return (Datum)0;
186194

187195
res= (JsonPath*)buf.data;
188196
SET_VARSIZE(res,buf.len);
@@ -225,9 +233,10 @@ jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
225233
* Recursive function converting given jsonpath parse item and all its
226234
* children into a binary representation.
227235
*/
228-
staticint
229-
flattenJsonPathParseItem(StringInfobuf,JsonPathParseItem*item,
230-
intnestingLevel,boolinsideArraySubscript)
236+
staticbool
237+
flattenJsonPathParseItem(StringInfobuf,int*result,structNode*escontext,
238+
JsonPathParseItem*item,intnestingLevel,
239+
boolinsideArraySubscript)
231240
{
232241
/* position from beginning of jsonpath data */
233242
int32pos=buf->len-JSONPATH_HDRSZ;
@@ -295,16 +304,22 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
295304
int32left=reserveSpaceForItemPointer(buf);
296305
int32right=reserveSpaceForItemPointer(buf);
297306

298-
chld= !item->value.args.left ?pos :
299-
flattenJsonPathParseItem(buf,item->value.args.left,
300-
nestingLevel+argNestingLevel,
301-
insideArraySubscript);
307+
if (!item->value.args.left)
308+
chld=pos;
309+
elseif (!flattenJsonPathParseItem(buf,&chld,escontext,
310+
item->value.args.left,
311+
nestingLevel+argNestingLevel,
312+
insideArraySubscript))
313+
return false;
302314
*(int32*) (buf->data+left)=chld-pos;
303315

304-
chld= !item->value.args.right ?pos :
305-
flattenJsonPathParseItem(buf,item->value.args.right,
306-
nestingLevel+argNestingLevel,
307-
insideArraySubscript);
316+
if (!item->value.args.right)
317+
chld=pos;
318+
elseif (!flattenJsonPathParseItem(buf,&chld,escontext,
319+
item->value.args.right,
320+
nestingLevel+argNestingLevel,
321+
insideArraySubscript))
322+
return false;
308323
*(int32*) (buf->data+right)=chld-pos;
309324
}
310325
break;
@@ -323,9 +338,11 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
323338
item->value.like_regex.patternlen);
324339
appendStringInfoChar(buf,'\0');
325340

326-
chld=flattenJsonPathParseItem(buf,item->value.like_regex.expr,
327-
nestingLevel,
328-
insideArraySubscript);
341+
if (!flattenJsonPathParseItem(buf,&chld,escontext,
342+
item->value.like_regex.expr,
343+
nestingLevel,
344+
insideArraySubscript))
345+
return false;
329346
*(int32*) (buf->data+offs)=chld-pos;
330347
}
331348
break;
@@ -341,10 +358,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
341358
{
342359
int32arg=reserveSpaceForItemPointer(buf);
343360

344-
chld= !item->value.arg ?pos :
345-
flattenJsonPathParseItem(buf,item->value.arg,
346-
nestingLevel+argNestingLevel,
347-
insideArraySubscript);
361+
if (!item->value.arg)
362+
chld=pos;
363+
elseif (!flattenJsonPathParseItem(buf,&chld,escontext,
364+
item->value.arg,
365+
nestingLevel+argNestingLevel,
366+
insideArraySubscript))
367+
return false;
348368
*(int32*) (buf->data+arg)=chld-pos;
349369
}
350370
break;
@@ -357,13 +377,13 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
357377
break;
358378
casejpiCurrent:
359379
if (nestingLevel <=0)
360-
ereport(ERROR,
380+
ereturn(escontext, false,
361381
(errcode(ERRCODE_SYNTAX_ERROR),
362382
errmsg("@ is not allowed in root expressions")));
363383
break;
364384
casejpiLast:
365385
if (!insideArraySubscript)
366-
ereport(ERROR,
386+
ereturn(escontext, false,
367387
(errcode(ERRCODE_SYNTAX_ERROR),
368388
errmsg("LAST is allowed only in array subscripts")));
369389
break;
@@ -383,15 +403,22 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
383403
{
384404
int32*ppos;
385405
int32topos;
386-
int32frompos=
387-
flattenJsonPathParseItem(buf,
388-
item->value.array.elems[i].from,
389-
nestingLevel, true)-pos;
406+
int32frompos;
407+
408+
if (!flattenJsonPathParseItem(buf,&frompos,escontext,
409+
item->value.array.elems[i].from,
410+
nestingLevel, true))
411+
return false;
412+
frompos-=pos;
390413

391414
if (item->value.array.elems[i].to)
392-
topos=flattenJsonPathParseItem(buf,
393-
item->value.array.elems[i].to,
394-
nestingLevel, true)-pos;
415+
{
416+
if (!flattenJsonPathParseItem(buf,&topos,escontext,
417+
item->value.array.elems[i].to,
418+
nestingLevel, true))
419+
return false;
420+
topos-=pos;
421+
}
395422
else
396423
topos=0;
397424

@@ -424,12 +451,17 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
424451

425452
if (item->next)
426453
{
427-
chld=flattenJsonPathParseItem(buf,item->next,nestingLevel,
428-
insideArraySubscript)-pos;
454+
if (!flattenJsonPathParseItem(buf,&chld,escontext,
455+
item->next,nestingLevel,
456+
insideArraySubscript))
457+
return false;
458+
chld-=pos;
429459
*(int32*) (buf->data+next)=chld;
430460
}
431461

432-
returnpos;
462+
if (result)
463+
*result=pos;
464+
return true;
433465
}
434466

435467
/*

‎src/backend/utils/adt/jsonpath_exec.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,8 @@ executeLikeRegex(JsonPathItem *jsp, JsonbValue *str, JsonbValue *rarg,
17211721
cxt->regex=
17221722
cstring_to_text_with_len(jsp->content.like_regex.pattern,
17231723
jsp->content.like_regex.patternlen);
1724-
cxt->cflags=jspConvertRegexFlags(jsp->content.like_regex.flags);
1724+
(void)jspConvertRegexFlags(jsp->content.like_regex.flags,
1725+
&(cxt->cflags),NULL);
17251726
}
17261727

17271728
if (RE_compile_and_execute(cxt->regex,str->val.string.val,

‎src/backend/utils/adt/jsonpath_gram.y

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ static JsonPathParseItem *makeItemUnary(JsonPathItemType type,
3838
static JsonPathParseItem *makeItemList(List *list);
3939
static JsonPathParseItem *makeIndexArray(List *list);
4040
static JsonPathParseItem *makeAny(int first,int last);
41-
static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr,
42-
JsonPathString *pattern,
43-
JsonPathString *flags);
41+
staticboolmakeItemLikeRegex(JsonPathParseItem *expr,
42+
JsonPathString *pattern,
43+
JsonPathString *flags,
44+
JsonPathParseItem ** result,
45+
structNode *escontext);
4446

4547
/*
4648
* Bison doesn't allocate anything that needs to live across parser calls,
@@ -57,6 +59,9 @@ static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr,
5759
%expect0
5860
%name-prefix="jsonpath_yy"
5961
%parse-param {JsonPathParseResult **result}
62+
%parse-param {structNode *escontext}
63+
%lex-param {JsonPathParseResult **result}
64+
%lex-param {structNode *escontext}
6065

6166
%union
6267
{
@@ -163,9 +168,20 @@ predicate:
163168
{$$ = makeItemUnary(jpiIsUnknown,$2); }
164169
|exprSTARTS_PWITH_Pstarts_with_initial
165170
{$$ = makeItemBinary(jpiStartsWith,$1,$4); }
166-
|exprLIKE_REGEX_PSTRING_P{$$ = makeItemLikeRegex($1, &$3,NULL); }
171+
|exprLIKE_REGEX_PSTRING_P
172+
{
173+
JsonPathParseItem *jppitem;
174+
if (! makeItemLikeRegex($1, &$3,NULL, &jppitem, escontext))
175+
YYABORT;
176+
$$ = jppitem;
177+
}
167178
|exprLIKE_REGEX_PSTRING_PFLAG_PSTRING_P
168-
{$$ = makeItemLikeRegex($1, &$3, &$5); }
179+
{
180+
JsonPathParseItem *jppitem;
181+
if (! makeItemLikeRegex($1, &$3, &$5, &jppitem, escontext))
182+
YYABORT;
183+
$$ = jppitem;
184+
}
169185
;
170186

171187
starts_with_initial:
@@ -472,9 +488,10 @@ makeAny(int first, int last)
472488
return v;
473489
}
474490

475-
staticJsonPathParseItem *
491+
staticbool
476492
makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
477-
JsonPathString *flags)
493+
JsonPathString *flags, JsonPathParseItem ** result,
494+
structNode *escontext)
478495
{
479496
JsonPathParseItem *v =makeItemType(jpiLikeRegex);
480497
inti;
@@ -506,7 +523,7 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
506523
v->value.like_regex.flags |= JSP_REGEX_QUOTE;
507524
break;
508525
default:
509-
ereport(ERROR,
526+
ereturn(escontext,false,
510527
(errcode(ERRCODE_SYNTAX_ERROR),
511528
errmsg("invalid input syntax for type %s","jsonpath"),
512529
errdetail("Unrecognized flag character\"%.*s\" in LIKE_REGEX predicate.",
@@ -515,22 +532,48 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
515532
}
516533
}
517534

518-
/* Convert flags to what RE_compile_and_cache needs*/
519-
cflags =jspConvertRegexFlags(v->value.like_regex.flags);
535+
/* Convert flags to what pg_regcomp needs*/
536+
if ( !jspConvertRegexFlags(v->value.like_regex.flags, &cflags, escontext))
537+
returnfalse;
520538

521539
/* check regex validity*/
522-
(void)RE_compile_and_cache(cstring_to_text_with_len(pattern->val,
523-
pattern->len),
524-
cflags, DEFAULT_COLLATION_OID);
540+
{
541+
regex_t re_tmp;
542+
pg_wchar *wpattern;
543+
int wpattern_len;
544+
int re_result;
545+
546+
wpattern = (pg_wchar *)palloc((pattern->len +1) *sizeof(pg_wchar));
547+
wpattern_len =pg_mb2wchar_with_len(pattern->val,
548+
wpattern,
549+
pattern->len);
550+
551+
if ((re_result =pg_regcomp(&re_tmp, wpattern, wpattern_len, cflags,
552+
DEFAULT_COLLATION_OID)) != REG_OKAY)
553+
{
554+
char errMsg[100];
555+
556+
/* See regexp.c for explanation*/
557+
CHECK_FOR_INTERRUPTS();
558+
pg_regerror(re_result, &re_tmp, errMsg,sizeof(errMsg));
559+
ereturn(escontext,false,
560+
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
561+
errmsg("invalid regular expression: %s", errMsg)));
562+
}
525563

526-
return v;
564+
pg_regfree(&re_tmp);
565+
}
566+
567+
*result = v;
568+
569+
returntrue;
527570
}
528571

529572
/*
530573
* Convert from XQuery regex flags to those recognized by our regex library.
531574
*/
532-
int
533-
jspConvertRegexFlags(uint32 xflags)
575+
bool
576+
jspConvertRegexFlags(uint32 xflags,int *result,structNode *escontext)
534577
{
535578
/* By default, XQuery is very nearly the same as Spencer's AREs*/
536579
intcflags = REG_ADVANCED;
@@ -561,18 +604,12 @@ jspConvertRegexFlags(uint32 xflags)
561604
* XQuery-style ignore-whitespace mode.
562605
*/
563606
if (xflags & JSP_REGEX_WSPACE)
564-
ereport(ERROR,
607+
ereturn(escontext,false,
565608
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
566609
errmsg("XQuery\"x\" flag (expanded regular expressions) is not implemented")));
567610
}
568611

569-
/*
570-
* We'll never need sub-match details at execution. While
571-
* RE_compile_and_execute would set this flag anyway, force it on here to
572-
* ensure that the regex cache entries created by makeItemLikeRegex are
573-
* useful.
574-
*/
575-
cflags |= REG_NOSUB;
612+
*result = cflags;
576613

577-
returncflags;
614+
returntrue;
578615
}

‎src/backend/utils/adt/jsonpath_internal.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,14 @@ typedef struct JsonPathString
2525
#include"utils/jsonpath.h"
2626
#include"jsonpath_gram.h"
2727

28-
externintjsonpath_yylex(YYSTYPE*yylval_param);
29-
externintjsonpath_yyparse(JsonPathParseResult**result);
30-
externvoidjsonpath_yyerror(JsonPathParseResult**result,constchar*message);
28+
#defineYY_DECL extern int jsonpath_yylex(YYSTYPE *yylval_param, \
29+
JsonPathParseResult **result, \
30+
struct Node *escontext)
31+
YY_DECL;
32+
externintjsonpath_yyparse(JsonPathParseResult**result,
33+
structNode*escontext);
34+
externvoidjsonpath_yyerror(JsonPathParseResult**result,
35+
structNode*escontext,
36+
constchar*message);
3137

3238
#endif/* JSONPATH_INTERNAL_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp