diff options
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 126d49452e2..cd3da46bc5e 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -93,6 +93,7 @@ static bool contain_subplans_walker(Node *node, void *context); static bool contain_mutable_functions_walker(Node *node, void *context); static bool contain_volatile_functions_walker(Node *node, void *context); static bool contain_nonstrict_functions_walker(Node *node, void *context); +static bool contain_leaky_functions_walker(Node *node, void *context); static Relids find_nonnullable_rels_walker(Node *node, bool top_level); static List *find_nonnullable_vars_walker(Node *node, bool top_level); static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK); @@ -1129,6 +1130,145 @@ contain_nonstrict_functions_walker(Node *node, void *context) context); } +/***************************************************************************** + * Check clauses for non-leakproof functions + *****************************************************************************/ + +/* + * contain_leaky_functions + * Recursively search for leaky functions within a clause. + * + * Returns true if any function call with side-effect may be present in the + * clause. Qualifiers from outside the a security_barrier view should not + * be pushed down into the view, lest the contents of tuples intended to be + * filtered out be revealed via side effects. + */ +bool +contain_leaky_functions(Node *clause) +{ + return contain_leaky_functions_walker(clause, NULL); +} + +static bool +contain_leaky_functions_walker(Node *node, void *context) +{ + if (node == NULL) + return false; + + switch (nodeTag(node)) + { + case T_Var: + case T_Const: + case T_Param: + case T_ArrayExpr: + case T_NamedArgExpr: + case T_BoolExpr: + case T_RelabelType: + case T_CaseExpr: + case T_CaseTestExpr: + case T_RowExpr: + case T_MinMaxExpr: + case T_NullTest: + case T_BooleanTest: + case T_List: + /* + * We know these node types don't contain function calls; but + * something further down in the node tree might. + */ + break; + + case T_FuncExpr: + { + FuncExpr *expr = (FuncExpr *) node; + + if (!get_func_leakproof(expr->funcid)) + return true; + } + break; + + case T_OpExpr: + case T_DistinctExpr: /* struct-equivalent to OpExpr */ + case T_NullIfExpr: /* struct-equivalent to OpExpr */ + { + OpExpr *expr = (OpExpr *) node; + + set_opfuncid(expr); + if (!get_func_leakproof(expr->opfuncid)) + return true; + } + break; + + case T_ScalarArrayOpExpr: + { + ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; + + set_sa_opfuncid(expr); + if (!get_func_leakproof(expr->opfuncid)) + return true; + } + break; + + case T_CoerceViaIO: + { + CoerceViaIO *expr = (CoerceViaIO *) node; + Oid funcid; + Oid ioparam; + bool varlena; + + getTypeInputInfo(exprType((Node *)expr->arg), + &funcid, &ioparam); + if (!get_func_leakproof(funcid)) + return true; + + getTypeOutputInfo(expr->resulttype, &funcid, &varlena); + if (!get_func_leakproof(funcid)) + return true; + } + break; + + case T_ArrayCoerceExpr: + { + ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node; + Oid funcid; + Oid ioparam; + bool varlena; + + getTypeInputInfo(exprType((Node *)expr->arg), + &funcid, &ioparam); + if (!get_func_leakproof(funcid)) + return true; + getTypeOutputInfo(expr->resulttype, &funcid, &varlena); + if (!get_func_leakproof(funcid)) + return true; + } + break; + + case T_RowCompareExpr: + { + RowCompareExpr *rcexpr = (RowCompareExpr *) node; + ListCell *opid; + + foreach(opid, rcexpr->opnos) + { + Oid funcid = get_opcode(lfirst_oid(opid)); + + if (!get_func_leakproof(funcid)) + return true; + } + } + break; + + default: + /* + * If we don't recognize the node tag, assume it might be leaky. + * This prevents an unexpected security hole if someone adds a new + * node type that can call a function. + */ + return true; + } + return expression_tree_walker(node, contain_leaky_functions_walker, + context); +} /* * find_nonnullable_rels |