diff options
Diffstat (limited to 'src/backend/utils/adt/jsonpath_gram.y')
-rw-r--r-- | src/backend/utils/adt/jsonpath_gram.y | 87 |
1 files changed, 62 insertions, 25 deletions
diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y index 2a56629cc3a..a460fa1bf75 100644 --- a/src/backend/utils/adt/jsonpath_gram.y +++ b/src/backend/utils/adt/jsonpath_gram.y @@ -38,9 +38,11 @@ static JsonPathParseItem *makeItemUnary(JsonPathItemType type, static JsonPathParseItem *makeItemList(List *list); static JsonPathParseItem *makeIndexArray(List *list); static JsonPathParseItem *makeAny(int first, int last); -static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr, - JsonPathString *pattern, - JsonPathString *flags); +static bool makeItemLikeRegex(JsonPathParseItem *expr, + JsonPathString *pattern, + JsonPathString *flags, + JsonPathParseItem ** result, + struct Node *escontext); /* * Bison doesn't allocate anything that needs to live across parser calls, @@ -57,6 +59,9 @@ static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr, %expect 0 %name-prefix="jsonpath_yy" %parse-param {JsonPathParseResult **result} +%parse-param {struct Node *escontext} +%lex-param {JsonPathParseResult **result} +%lex-param {struct Node *escontext} %union { @@ -163,9 +168,20 @@ predicate: { $$ = makeItemUnary(jpiIsUnknown, $2); } | expr STARTS_P WITH_P starts_with_initial { $$ = makeItemBinary(jpiStartsWith, $1, $4); } - | expr LIKE_REGEX_P STRING_P { $$ = makeItemLikeRegex($1, &$3, NULL); } + | expr LIKE_REGEX_P STRING_P + { + JsonPathParseItem *jppitem; + if (! makeItemLikeRegex($1, &$3, NULL, &jppitem, escontext)) + YYABORT; + $$ = jppitem; + } | expr LIKE_REGEX_P STRING_P FLAG_P STRING_P - { $$ = makeItemLikeRegex($1, &$3, &$5); } + { + JsonPathParseItem *jppitem; + if (! makeItemLikeRegex($1, &$3, &$5, &jppitem, escontext)) + YYABORT; + $$ = jppitem; + } ; starts_with_initial: @@ -472,9 +488,10 @@ makeAny(int first, int last) return v; } -static JsonPathParseItem * +static bool makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern, - JsonPathString *flags) + JsonPathString *flags, JsonPathParseItem ** result, + struct Node *escontext) { JsonPathParseItem *v = makeItemType(jpiLikeRegex); int i; @@ -506,7 +523,7 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern, v->value.like_regex.flags |= JSP_REGEX_QUOTE; break; default: - ereport(ERROR, + ereturn(escontext, false, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid input syntax for type %s", "jsonpath"), errdetail("Unrecognized flag character \"%.*s\" in LIKE_REGEX predicate.", @@ -515,22 +532,48 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern, } } - /* Convert flags to what RE_compile_and_cache needs */ - cflags = jspConvertRegexFlags(v->value.like_regex.flags); + /* Convert flags to what pg_regcomp needs */ + if ( !jspConvertRegexFlags(v->value.like_regex.flags, &cflags, escontext)) + return false; /* check regex validity */ - (void) RE_compile_and_cache(cstring_to_text_with_len(pattern->val, - pattern->len), - cflags, DEFAULT_COLLATION_OID); + { + regex_t re_tmp; + pg_wchar *wpattern; + int wpattern_len; + int re_result; + + wpattern = (pg_wchar *) palloc((pattern->len + 1) * sizeof(pg_wchar)); + wpattern_len = pg_mb2wchar_with_len(pattern->val, + wpattern, + pattern->len); + + if ((re_result = pg_regcomp(&re_tmp, wpattern, wpattern_len, cflags, + DEFAULT_COLLATION_OID)) != REG_OKAY) + { + char errMsg[100]; + + /* See regexp.c for explanation */ + CHECK_FOR_INTERRUPTS(); + pg_regerror(re_result, &re_tmp, errMsg, sizeof(errMsg)); + ereturn(escontext, false, + (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION), + errmsg("invalid regular expression: %s", errMsg))); + } - return v; + pg_regfree(&re_tmp); + } + + *result = v; + + return true; } /* * Convert from XQuery regex flags to those recognized by our regex library. */ -int -jspConvertRegexFlags(uint32 xflags) +bool +jspConvertRegexFlags(uint32 xflags, int *result, struct Node *escontext) { /* By default, XQuery is very nearly the same as Spencer's AREs */ int cflags = REG_ADVANCED; @@ -561,18 +604,12 @@ jspConvertRegexFlags(uint32 xflags) * XQuery-style ignore-whitespace mode. */ if (xflags & JSP_REGEX_WSPACE) - ereport(ERROR, + ereturn(escontext, false, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("XQuery \"x\" flag (expanded regular expressions) is not implemented"))); } - /* - * We'll never need sub-match details at execution. While - * RE_compile_and_execute would set this flag anyway, force it on here to - * ensure that the regex cache entries created by makeItemLikeRegex are - * useful. - */ - cflags |= REG_NOSUB; + *result = cflags; - return cflags; + return true; } |