8000 Further fixes to the pg_get_expr() security fix in back branches. · danielcode/postgres@46286d6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 46286d6

Browse files
committed
Further fixes to the pg_get_expr() security fix in back branches.
It now emerges that the JDBC driver expects to be able to use pg_get_expr() on an output of a sub-SELECT. So extend the check logic to be able to recurse into a sub-SELECT to see if the argument is ultimately coming from an appropriate column. Per report from Thomas Kellerer.
1 parent 74515dc commit 46286d6

File tree

1 file changed

+56
-24
lines changed

1 file changed

+56
-24
lines changed

src/backend/parser/parse_func.c

Lines changed: 56 additions & 24 deletions
< 8000 td data-grid-cell-id="diff-4f5a8d08e1850109ddee47a33c6d76fb4fa5ab98408655e402da58e716fd8c2f-1456-1458-0" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-additionNum-bgColor, var(--diffBlob-addition-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "parser/parse_func.h"
3030
#include "parser/parse_relation.h"
3131
#include "parser/parse_type.h"
32+
#include "parser/parsetree.h"
3233
#include "utils/builtins.h"
3334
#include "utils/fmgroids.h"
3435
#include "utils/lsyscache.h"
@@ -42,6 +43,7 @@ static Oid **argtype_inherit(int nargs, Oid *argtypes);
4243
static int find_inheritors(Oid relid, Oid **supervec);
4344
static Oid **gen_cross_product(InhPaths *arginh, int nargs);
4445
static void unknown_attribute(ParseState *pstate, Node *relref, char *attname);
46+
static bool check_pg_get_expr_arg(ParseState *pstate, Node *arg, int netlevelsup);
4547

4648

4749
/*
@@ -1439,9 +1441,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
14391441
void
14401442
check_pg_get_expr_args(ParseState *pstate, Oid fnoid, List *args)
14411443
{
1442-
bool allowed = false;
14431444
Node *arg;
1444-
int netlevelsup;
14451445

14461446
/* if not being called for pg_get_expr, do nothing */
14471447
if (fnoid != F_PG_GET_EXPR && fnoid != F_PG_GET_EXPR_EXT)
@@ -1453,59 +1453,91 @@ check_pg_get_expr_args(ParseState *pstate, Oid fnoid, List *args)
14531453

14541454
/*
14551455
* The first argument must be a Var referencing one of the allowed
1456-
* system-catalog columns. It could be a join alias Var, though.
1456+
* system-catalog columns. It could be a join alias Var or subquery
1457+
* reference Var, though, so we need a recursive subroutine to chase
1458+
* through those possibilities.
14571459
*/
14581460
Assert(list_length(args) > 1);
14591461
arg = (Node *) linitial(args);
1460-
netlevelsup = 0;
14611462

1462-
restart:
1463-
if (IsA(arg, Var))
1463+
if (!check_pg_get_expr_arg(pstate, arg, 0))
1464+
ereport(ERROR,
1465+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1466+
errmsg("argument to pg_get_expr() must come from system catalogs")));
1467+
}
1468+
1469+
static bool
1470+
check_pg_get_expr_arg(ParseState *pstate, Node *arg, int netlevelsup)
1471+
{
1472+
if (arg && IsA(arg, Var))
14641473
{
14651474
Var *var = (Var *) arg;
14661475
RangeTblEntry *rte;
1476+
AttrNumber attnum;
14671477

14681478
netlevelsup += var->varlevelsup;
14691479
rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
1480+
attnum = var->varattno;
14701481

14711482
if (rte->rtekind == RTE_JOIN)
14721483
{
1473-
/* Expand join alias reference */
1474-
if (var->varattno > 0 &&
1475-
var->varattno <= list_length(rte->joinaliasvars))
1484+
/* Recursively examine join alias variable */
1485+
if (attnum > 0 &&
1486+
attnum <= list_length(rte->joinaliasvars))
14761487
{
1477-
arg = (Node *) list_nth(rte->joinaliasvars, var->varattno - 1);
1478-
goto restart;
1488+
arg = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
1489+
return check_pg_get_expr_arg(pstate, arg, netlevelsup);
14791490
}
14801491
}
1492+
else if (rte->rtekind == RTE_SUBQUERY)
1493+
{
1494+
/* Subselect-in-FROM: examine sub-select's output expr */
1495+
TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
1496+
attnum);
1497+
ParseState mypstate;
1498+
1499+
if (ste == NULL || ste->resdom->resjunk)
1500+
elog(ERROR, "subquery %s does not have attribute %d",
1501+
rte->eref->aliasname, attnum);
1502+
arg = (Node *) ste->expr;
1503+
1504+
/* 628C
1505+
* Recurse into the sub-select to see what its expr refers to.
1506+
* We have to build an additional level of ParseState to keep in
1507+
* step with varlevelsup in the subselect.
1508+
*/
1509+
MemSet(&mypstate, 0, sizeof(mypstate));
1510+
mypstate.parentParseState = pstate;
1511+
mypstate.p_rtable = rte->subquery->rtable;
1512+
/* don't bother filling the rest of the fake pstate */
1513+
1514+
return check_pg_get_expr_arg(&mypstate, arg, 0);
1515+
}
14811516
else if (rte->rtekind == RTE_RELATION)
14821517
{
14831518
if (rte->relid == get_system_catalog_relid(IndexRelationName))
14841519
{
1485-
if (var->varattno == Anum_pg_index_indexprs ||
1486-
var->varattno == Anum_pg_index_indpred)
1487-
allowed = true;
1520+
if (attnum == Anum_pg_index_indexprs ||
1521+
attnum == Anum_pg_index_indpred)
1522+
return true;
14881523
}
14891524
else if (rte->relid == get_system_catalog_relid(AttrDefaultRelationName))
14901525
{
1491-
if (var->varattno == Anum_pg_attrdef_adbin)
1492-
allowed = true;
1526+
if (attnum == Anum_pg_attrdef_adbin)
1527+
return true;
14931528
}
14941529
else if (rte->relid == get_system_catalog_relid(ConstraintRelationName))
14951530
{
1496-
if (var->varattno == Anum_pg_constraint_conbin)
1497-
allowed = true;
1531+
if (attnum == Anum_pg_constraint_conbin)
1532+
return true;
14981533
}
14991534
else if (rte->relid == get_system_catalog_relid(TypeRelationName))
15001535
{
1501-
if (var->varattno == Anum_pg_type_typdefaultbin)
1502-
allowed = true;
1536+
if (attnum == Anum_pg_type_typdefaultbin)
1537+
return true;
15031538
}
15041539
}
15051540
}
15061541

1507-
if (!allowed)
1508-
ereport(ERROR,
1509-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1510-
errmsg("argument to pg_get_expr() must come from system catalogs")));
1542+
return false;
15111543
}

0 commit comments

Comments
 (0)
0