mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
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
This commit is contained in:
@ -4278,6 +4278,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
|
|||||||
JsonPathVariable *var = palloc(sizeof(*var));
|
JsonPathVariable *var = palloc(sizeof(*var));
|
||||||
|
|
||||||
var->name = argname->sval;
|
var->name = argname->sval;
|
||||||
|
var->namelen = strlen(var->name);
|
||||||
var->typid = exprType((Node *) argexpr);
|
var->typid = exprType((Node *) argexpr);
|
||||||
var->typmod = exprTypmod((Node *) argexpr);
|
var->typmod = exprTypmod((Node *) argexpr);
|
||||||
|
|
||||||
|
@ -2994,7 +2994,8 @@ GetJsonPathVar(void *cxt, char *varName, int varNameLen,
|
|||||||
{
|
{
|
||||||
JsonPathVariable *curvar = lfirst(lc);
|
JsonPathVariable *curvar = lfirst(lc);
|
||||||
|
|
||||||
if (!strncmp(curvar->name, varName, varNameLen))
|
if (curvar->namelen == varNameLen &&
|
||||||
|
strncmp(curvar->name, varName, varNameLen) == 0)
|
||||||
{
|
{
|
||||||
var = curvar;
|
var = curvar;
|
||||||
break;
|
break;
|
||||||
@ -4118,6 +4119,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
|
|||||||
JsonPathVariable *var = palloc(sizeof(*var));
|
JsonPathVariable *var = palloc(sizeof(*var));
|
||||||
|
|
||||||
var->name = pstrdup(name->sval);
|
var->name = pstrdup(name->sval);
|
||||||
|
var->namelen = strlen(var->name);
|
||||||
var->typid = exprType((Node *) state->expr);
|
var->typid = exprType((Node *) state->expr);
|
||||||
var->typmod = exprTypmod((Node *) state->expr);
|
var->typmod = exprTypmod((Node *) state->expr);
|
||||||
|
|
||||||
|
@ -287,6 +287,7 @@ extern bool jspConvertRegexFlags(uint32 xflags, int *result,
|
|||||||
typedef struct JsonPathVariable
|
typedef struct JsonPathVariable
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
int namelen; /* strlen(name) as cache for GetJsonPathVar() */
|
||||||
Oid typid;
|
Oid typid;
|
||||||
int32 typmod;
|
int32 typmod;
|
||||||
Datum value;
|
Datum value;
|
||||||
|
@ -1334,3 +1334,14 @@ SELECT json_value('"aaa"', path RETURNING json) FROM jsonpaths;
|
|||||||
"aaa"
|
"aaa"
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- Test PASSING argument parsing
|
||||||
|
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xy);
|
||||||
|
ERROR: could not find jsonpath variable "xyz"
|
||||||
|
SELECT JSON_QUERY(jsonb 'null', '$xy' PASSING 1 AS xyz);
|
||||||
|
ERROR: could not find jsonpath variable "xy"
|
||||||
|
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xyz);
|
||||||
|
json_query
|
||||||
|
------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@ -454,3 +454,8 @@ SELECT JSON_QUERY(NULL FORMAT JSON, '$');
|
|||||||
-- Test non-const jsonpath
|
-- Test non-const jsonpath
|
||||||
CREATE TEMP TABLE jsonpaths (path) AS SELECT '$';
|
CREATE TEMP TABLE jsonpaths (path) AS SELECT '$';
|
||||||
SELECT json_value('"aaa"', path RETURNING json) FROM jsonpaths;
|
SELECT json_value('"aaa"', path RETURNING json) FROM jsonpaths;
|
||||||
|
|
||||||
|
-- Test PASSING argument parsing
|
||||||
|
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xy);
|
||||||
|
SELECT JSON_QUERY(jsonb 'null', '$xy' PASSING 1 AS xyz);
|
||||||
|
SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xyz);
|
||||||
|
Reference in New Issue
Block a user