diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index 69bfe4c1578d92d6639ad3384c18b65dfc9f743a..fc5ed839376018f1cba6d698727f626e226c615f 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.96 2008/11/02 01:45:27 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.97 2008/11/14 19:47:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,6 +61,7 @@ AggregateCreate(const char *aggName, Oid finalfn = InvalidOid; /* can be omitted */ Oid sortop = InvalidOid; /* can be omitted */ bool hasPolyArg; + bool hasInternalArg; Oid rettype; Oid finaltype; Oid *fnArgs; @@ -78,15 +79,15 @@ AggregateCreate(const char *aggName, if (!aggtransfnName) elog(ERROR, "aggregate must have a transition function"); - /* check for polymorphic arguments */ + /* check for polymorphic and INTERNAL arguments */ hasPolyArg = false; + hasInternalArg = false; for (i = 0; i < numArgs; i++) { if (IsPolymorphicType(aggArgTypes[i])) - { hasPolyArg = true; - break; - } + else if (aggArgTypes[i] == INTERNALOID) + hasInternalArg = true; } /* @@ -177,6 +178,18 @@ AggregateCreate(const char *aggName, errdetail("An aggregate returning a polymorphic type " "must have at least one polymorphic argument."))); + /* + * Also, the return type can't be INTERNAL unless there's at least one + * INTERNAL argument. This is the same type-safety restriction we + * enforce for regular functions, but at the level of aggregates. We + * must test this explicitly because we allow INTERNAL as the transtype. + */ + if (finaltype == INTERNALOID && !hasInternalArg) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("unsafe use of pseudo-type \"internal\""), + errdetail("A function returning \"internal\" must have at least one \"internal\" argument."))); + /* handle sortop, if supplied */ if (aggsortopName) { diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index a8c9f1199e44fc19ac4df32663d9735eb600d108..5bbb4bfdf745fa430d6161cc2caf9086e5bb50a1 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.46 2008/06/08 21:09:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.47 2008/11/14 19:47:50 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -173,15 +173,24 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) * * transtype can't be a pseudo-type, since we need to be able to store * values of the transtype. However, we can allow polymorphic transtype - * in some cases (AggregateCreate will check). + * in some cases (AggregateCreate will check). Also, we allow "internal" + * for functions that want to pass pointers to private data structures; + * but allow that only to superusers, since you could crash the system + * (or worse) by connecting up incompatible internal-using functions + * in an aggregate. */ transTypeId = typenameTypeId(NULL, transType, NULL); if (get_typtype(transTypeId) == TYPTYPE_PSEUDO && !IsPolymorphicType(transTypeId)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregate transition data type cannot be %s", - format_type_be(transTypeId)))); + { + if (transTypeId == INTERNALOID && superuser()) + /* okay */ ; + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("aggregate transition data type cannot be %s", + format_type_be(transTypeId)))); + } /* * Most of the argument-checking is done inside of AggregateCreate