mirror of
https://github.com/postgres/postgres.git
synced 2025-11-22 12:22:45 +03:00
Fix type-safety problem with parallel aggregate serial/deserialization.
The original specification for this called for the deserialization function to have signature "deserialize(serialtype) returns transtype", which is a security violation if transtype is INTERNAL (which it always would be in practice) and serialtype is not (which ditto). The patch blithely overrode the opr_sanity check for that, which was sloppy-enough work in itself, but the indisputable reason this cannot be allowed to stand is that CREATE FUNCTION will reject such a signature and thus it'd be impossible for extensions to create parallelizable aggregates. The minimum fix to make the signature type-safe is to add a second, dummy argument of type INTERNAL. But to lock it down a bit more and make misuse of INTERNAL-accepting functions less likely, let's get rid of the ability to specify a "serialtype" for an aggregate and just say that the only useful serialtype is BYTEA --- which, in practice, is the only interesting value anyway, due to the usefulness of the send/recv infrastructure for this purpose. That means we only have to allow "serialize(internal) returns bytea" and "deserialize(bytea, internal) returns internal" as the signatures for these support functions. In passing fix bogus signature of int4_avg_combine, which I found thanks to adding an opr_sanity check on combinefunc signatures. catversion bump due to removing pg_aggregate.aggserialtype and adjusting signatures of assorted built-in functions. David Rowley and Tom Lane Discussion: <27247.1466185504@sss.pgh.pa.us>
This commit is contained in:
@@ -67,7 +67,6 @@ AggregateCreate(const char *aggName,
|
||||
bool mfinalfnExtraArgs,
|
||||
List *aggsortopName,
|
||||
Oid aggTransType,
|
||||
Oid aggSerialType,
|
||||
int32 aggTransSpace,
|
||||
Oid aggmTransType,
|
||||
int32 aggmTransSpace,
|
||||
@@ -440,44 +439,42 @@ AggregateCreate(const char *aggName,
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the serialization function, if present. We must ensure that
|
||||
* the return type of this function is the same as the specified
|
||||
* serialType.
|
||||
* Validate the serialization function, if present.
|
||||
*/
|
||||
if (aggserialfnName)
|
||||
{
|
||||
fnArgs[0] = aggTransType;
|
||||
fnArgs[0] = INTERNALOID;
|
||||
|
||||
serialfn = lookup_agg_function(aggserialfnName, 1,
|
||||
fnArgs, variadicArgType,
|
||||
&rettype);
|
||||
|
||||
if (rettype != aggSerialType)
|
||||
if (rettype != BYTEAOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("return type of serialization function %s is not %s",
|
||||
NameListToString(aggserialfnName),
|
||||
format_type_be(aggSerialType))));
|
||||
format_type_be(BYTEAOID))));
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the deserialization function, if present. We must ensure that
|
||||
* the return type of this function is the same as the transType.
|
||||
* Validate the deserialization function, if present.
|
||||
*/
|
||||
if (aggdeserialfnName)
|
||||
{
|
||||
fnArgs[0] = aggSerialType;
|
||||
fnArgs[0] = BYTEAOID;
|
||||
fnArgs[1] = INTERNALOID; /* dummy argument for type safety */
|
||||
|
||||
deserialfn = lookup_agg_function(aggdeserialfnName, 1,
|
||||
deserialfn = lookup_agg_function(aggdeserialfnName, 2,
|
||||
fnArgs, variadicArgType,
|
||||
&rettype);
|
||||
|
||||
if (rettype != aggTransType)
|
||||
if (rettype != INTERNALOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("return type of deserialization function %s is not %s",
|
||||
NameListToString(aggdeserialfnName),
|
||||
format_type_be(aggTransType))));
|
||||
format_type_be(INTERNALOID))));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -661,7 +658,6 @@ AggregateCreate(const char *aggName,
|
||||
values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
|
||||
values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
|
||||
values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
|
||||
values[Anum_pg_aggregate_aggserialtype - 1] = ObjectIdGetDatum(aggSerialType);
|
||||
values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
|
||||
values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType);
|
||||
values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace);
|
||||
@@ -688,8 +684,7 @@ AggregateCreate(const char *aggName,
|
||||
* Create dependencies for the aggregate (above and beyond those already
|
||||
* made by ProcedureCreate). Note: we don't need an explicit dependency
|
||||
* on aggTransType since we depend on it indirectly through transfn.
|
||||
* Likewise for aggmTransType using the mtransfunc, and also for
|
||||
* aggSerialType using the serialfn, if they exist.
|
||||
* Likewise for aggmTransType using the mtransfunc, if it exists.
|
||||
*/
|
||||
|
||||
/* Depends on transition function */
|
||||
|
||||
Reference in New Issue
Block a user