Skip to content

Commit 0f271e8

Browse files
committed
SQL/JSON: Correct jsonpath variable name matching
Previously, GetJsonPathVar() allowed a jsonpath expression to reference any prefix of a PASSING variable's name. For example, the following query would incorrectly work: SELECT JSON_QUERY(context_item, jsonpath '$xy' PASSING val AS xyz); The fix ensures that the length of the variable name mentioned in a jsonpath expression matches exactly with the name of the PASSING variable before comparing the strings using strncmp(). Reported-by: Alvaro Herrera (off-list) Discussion: https://postgr.es/m/CA+HiwqFGkLWMvELBH6E4SQ45qUHthgcRH6gCJL20OsYDRtFx_w@mail.gmail.com
1 parent 5e05a0e commit 0f271e8

File tree

5 files changed

+21
-1
lines changed

5 files changed

+21
-1
lines changed

src/backend/executor/execExpr.c

+1
Original file line numberDiff line numberDiff line change
@@ -4278,6 +4278,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
42784278
JsonPathVariable *var = palloc(sizeof(*var));
42794279

42804280
var->name = argname->sval;
4281+
var->namelen = strlen(var->name);
42814282
var->typid = exprType((Node *) argexpr);
42824283
var->typmod = exprTypmod((Node *) argexpr);
42834284

src/backend/utils/adt/jsonpath_exec.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -2994,7 +2994,8 @@ GetJsonPathVar(void *cxt, char *varName, int varNameLen,
29942994
{
29952995
JsonPathVariable *curvar = lfirst(lc);
29962996

2997-
if (!strncmp(curvar->name, varName, varNameLen))
2997+
if (curvar->namelen == varNameLen &&
2998+
strncmp(curvar->name, varName, varNameLen) == 0)
29982999
{
29993000
var = curvar;
30003001
break;
@@ -4118,6 +4119,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
41184119
JsonPathVariable *var = palloc(sizeof(*var));
41194120

41204121
var->name = pstrdup(name->sval);
4122+
var->namelen = strlen(var->name);
41214123
var->typid = exprType((Node *) state->expr);
41224124
var->typmod = exprTypmod((Node *) state->expr);
41234125

src/include/utils/jsonpath.h

+1
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ extern bool jspConvertRegexFlags(uint32 xflags, int *result,
287287
typedef struct JsonPathVariable
288288
{
289289
char *name;
290+
int namelen; /* strlen(name) as cache for GetJsonPathVar() */
290291
Oid typid;
291292
int32 typmod;
292293
Datum value;

src/test/regress/expected/sqljson_queryfuncs.out

+11
Original file line numberDiff line numberDiff line change
@@ -1334,3 +1334,14 @@ SELECT json_value('"aaa"', path RETURNING json) FROM jsonpaths;
13341334
"aaa"
13351335
(1 row)
13361336

1337+
-- Test PASSING argument parsing
1338+
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xy);
1339+
ERROR: could not find jsonpath variable "xyz"
1340+
SELECT JSON_QUERY(jsonb 'null', '$xy' PASSING 1 AS xyz);
1341+
ERROR: could not find jsonpath variable "xy"
1342+
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xyz);
1343+
json_query
1344+
------------
1345+
1
1346+
(1 row)
1347+

src/test/regress/sql/sqljson_queryfuncs.sql

+5
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,8 @@ SELECT JSON_QUERY(NULL FORMAT JSON, '$');
454454
-- Test non-const jsonpath
455455
CREATE TEMP TABLE jsonpaths (path) AS SELECT '$';
456456
SELECT json_value('"aaa"', path RETURNING json) FROM jsonpaths;
457+
458+
-- Test PASSING argument parsing
459+
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xy);
460+
SELECT JSON_QUERY(jsonb 'null', '$xy' PASSING 1 AS xyz);
461+
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xyz);

0 commit comments

Comments
 (0)