diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-08-05 11:20:21 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-08-05 11:20:31 -0400 |
commit | 4766dce0dd1a1a26db253dfc81773a2c55cd2555 (patch) | |
tree | 5e80ec92efbb103b7003b2361cc3b9fe1aeea40b /src/backend/executor/nodeSubplan.c | |
parent | ffa2d37e5fbd1243f918f622113d6e371667e5a0 (diff) | |
download | postgresql-4766dce0dd1a1a26db253dfc81773a2c55cd2555.tar.gz postgresql-4766dce0dd1a1a26db253dfc81773a2c55cd2555.zip |
Fix choice of comparison operators for cross-type hashed subplans.
Commit bf6c614a2 rearranged the lookup of the comparison operators
needed in a hashed subplan, and in so doing, broke the cross-type
case: it caused the original LHS-vs-RHS operator to be used to compare
hash table entries too (which of course are all of the RHS type).
This leads to C functions being passed a Datum that is not of the
type they expect, with the usual hazards of crashes and unauthorized
server memory disclosure.
For the set of hashable cross-type operators present in v11 core
Postgres, this bug is nearly harmless on 64-bit machines, which
may explain why it escaped earlier detection. But it is a live
security hazard on 32-bit machines; and of course there may be
extensions that add more hashable cross-type operators, which
would increase the risk.
Reported by Andreas Seltenreich. Back-patch to v11 where the
problem came in.
Security: CVE-2019-10209
Diffstat (limited to 'src/backend/executor/nodeSubplan.c')
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index f6445e286ac..1991b90a55f 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -860,6 +860,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) i; TupleDesc tupDescLeft; TupleDesc tupDescRight; + Oid *cross_eq_funcoids; TupleTableSlot *slot; List *oplist, *lefttlist, @@ -923,6 +924,9 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) sstate->tab_collations = (Oid *) palloc(ncols * sizeof(Oid)); sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); sstate->cur_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); + /* we'll need the cross-type equality fns below, but not in sstate */ + cross_eq_funcoids = (Oid *) palloc(ncols * sizeof(Oid)); + i = 1; foreach(l, oplist) { @@ -952,7 +956,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) righttlist = lappend(righttlist, tle); /* Lookup the equality function (potentially cross-type) */ - sstate->tab_eq_funcoids[i - 1] = opexpr->opfuncid; + cross_eq_funcoids[i - 1] = opexpr->opfuncid; fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]); fmgr_info_set_expr((Node *) opexpr, &sstate->cur_eq_funcs[i - 1]); @@ -961,7 +965,9 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) NULL, &rhs_eq_oper)) elog(ERROR, "could not find compatible hash operator for operator %u", opexpr->opno); - fmgr_info(get_opcode(rhs_eq_oper), &sstate->tab_eq_funcs[i - 1]); + sstate->tab_eq_funcoids[i - 1] = get_opcode(rhs_eq_oper); + fmgr_info(sstate->tab_eq_funcoids[i - 1], + &sstate->tab_eq_funcs[i - 1]); /* Lookup the associated hash functions */ if (!get_op_hash_functions(opexpr->opno, @@ -1003,16 +1009,15 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) /* * Create comparator for lookups of rows in the table (potentially - * across-type comparison). + * cross-type comparisons). */ sstate->cur_eq_comp = ExecBuildGroupingEqual(tupDescLeft, tupDescRight, &TTSOpsVirtual, &TTSOpsMinimalTuple, ncols, sstate->keyColIdx, - sstate->tab_eq_funcoids, + cross_eq_funcoids, sstate->tab_collations, parent); - } return sstate; |