mirror of
https://github.com/postgres/postgres.git
synced 2025-04-29 13:56:47 +03:00
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
This commit is contained in:
parent
ffa2d37e5f
commit
4766dce0dd
@ -860,6 +860,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
|
|||||||
i;
|
i;
|
||||||
TupleDesc tupDescLeft;
|
TupleDesc tupDescLeft;
|
||||||
TupleDesc tupDescRight;
|
TupleDesc tupDescRight;
|
||||||
|
Oid *cross_eq_funcoids;
|
||||||
TupleTableSlot *slot;
|
TupleTableSlot *slot;
|
||||||
List *oplist,
|
List *oplist,
|
||||||
*lefttlist,
|
*lefttlist,
|
||||||
@ -923,6 +924,9 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
|
|||||||
sstate->tab_collations = (Oid *) palloc(ncols * sizeof(Oid));
|
sstate->tab_collations = (Oid *) palloc(ncols * sizeof(Oid));
|
||||||
sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
|
sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));
|
||||||
sstate->cur_eq_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;
|
i = 1;
|
||||||
foreach(l, oplist)
|
foreach(l, oplist)
|
||||||
{
|
{
|
||||||
@ -952,7 +956,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
|
|||||||
righttlist = lappend(righttlist, tle);
|
righttlist = lappend(righttlist, tle);
|
||||||
|
|
||||||
/* Lookup the equality function (potentially cross-type) */
|
/* 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(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]);
|
||||||
fmgr_info_set_expr((Node *) opexpr, &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))
|
NULL, &rhs_eq_oper))
|
||||||
elog(ERROR, "could not find compatible hash operator for operator %u",
|
elog(ERROR, "could not find compatible hash operator for operator %u",
|
||||||
opexpr->opno);
|
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 */
|
/* Lookup the associated hash functions */
|
||||||
if (!get_op_hash_functions(opexpr->opno,
|
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
|
* Create comparator for lookups of rows in the table (potentially
|
||||||
* across-type comparison).
|
* cross-type comparisons).
|
||||||
*/
|
*/
|
||||||
sstate->cur_eq_comp = ExecBuildGroupingEqual(tupDescLeft, tupDescRight,
|
sstate->cur_eq_comp = ExecBuildGroupingEqual(tupDescLeft, tupDescRight,
|
||||||
&TTSOpsVirtual, &TTSOpsMinimalTuple,
|
&TTSOpsVirtual, &TTSOpsMinimalTuple,
|
||||||
ncols,
|
ncols,
|
||||||
sstate->keyColIdx,
|
sstate->keyColIdx,
|
||||||
sstate->tab_eq_funcoids,
|
cross_eq_funcoids,
|
||||||
sstate->tab_collations,
|
sstate->tab_collations,
|
||||||
parent);
|
parent);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sstate;
|
return sstate;
|
||||||
|
@ -764,6 +764,30 @@ select * from outer_text where (f1, f2) not in (select * from inner_text);
|
|||||||
b |
|
b |
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Another test case for cross-type hashed subplans: comparison of
|
||||||
|
-- inner-side values must be done with appropriate operator
|
||||||
|
--
|
||||||
|
explain (verbose, costs off)
|
||||||
|
select 'foo'::text in (select 'bar'::name union all select 'bar'::name);
|
||||||
|
QUERY PLAN
|
||||||
|
-------------------------------------
|
||||||
|
Result
|
||||||
|
Output: (hashed SubPlan 1)
|
||||||
|
SubPlan 1
|
||||||
|
-> Append
|
||||||
|
-> Result
|
||||||
|
Output: 'bar'::name
|
||||||
|
-> Result
|
||||||
|
Output: 'bar'::name
|
||||||
|
(8 rows)
|
||||||
|
|
||||||
|
select 'foo'::text in (select 'bar'::name union all select 'bar'::name);
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Test case for premature memory release during hashing of subplan output
|
-- Test case for premature memory release during hashing of subplan output
|
||||||
--
|
--
|
||||||
|
@ -452,6 +452,16 @@ insert into inner_text values ('a', null);
|
|||||||
|
|
||||||
select * from outer_text where (f1, f2) not in (select * from inner_text);
|
select * from outer_text where (f1, f2) not in (select * from inner_text);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Another test case for cross-type hashed subplans: comparison of
|
||||||
|
-- inner-side values must be done with appropriate operator
|
||||||
|
--
|
||||||
|
|
||||||
|
explain (verbose, costs off)
|
||||||
|
select 'foo'::text in (select 'bar'::name union all select 'bar'::name);
|
||||||
|
|
||||||
|
select 'foo'::text in (select 'bar'::name union all select 'bar'::name);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Test case for premature memory release during hashing of subplan output
|
-- Test case for premature memory release during hashing of subplan output
|
||||||
--
|
--
|
||||||
|
Loading…
x
Reference in New Issue
Block a user