1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-09 13:09:39 +03:00

Repair insufficiently careful type checking for SQL-language functions:

we should check that the function code returns the claimed result datatype
every time we parse the function for execution.  Formerly, for simple
scalar result types we assumed the creation-time check was sufficient, but
this fails if the function selects from a table that's been redefined since
then, and even more obviously fails if check_function_bodies had been OFF.

This is a significant security hole: not only can one trivially crash the
backend, but with appropriate misuse of pass-by-reference datatypes it is
possible to read out arbitrary locations in the server process's memory,
which could allow retrieving database content the user should not be able
to see.  Our thanks to Jeff Trout for the initial report.

Security: CVE-2007-0555
This commit is contained in:
Tom Lane
2007-02-02 00:03:30 +00:00
parent 139e4a2635
commit 088ef257fe
2 changed files with 29 additions and 57 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.201.2.1 2005/11/22 18:23:12 momjian Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.201.2.2 2007/02/02 00:03:30 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -2293,7 +2293,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
eval_const_expressions_context *context)
{
Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
bool polymorphic = false;
Oid *argtypes;
char *src;
Datum tmp;
@@ -2356,15 +2355,10 @@ inline_function(Oid funcid, Oid result_type, List *args,
if (argtypes[i] == ANYARRAYOID ||
argtypes[i] == ANYELEMENTOID)
{
polymorphic = true;
argtypes[i] = exprType((Node *) list_nth(args, i));
}
}
if (funcform->prorettype == ANYARRAYOID ||
funcform->prorettype == ANYELEMENTOID)
polymorphic = true;
/* Fetch and parse the function body */
tmp = SysCacheGetAttr(PROCOID,
func_tuple,
@@ -2417,15 +2411,13 @@ inline_function(Oid funcid, Oid result_type, List *args,
newexpr = (Node *) ((TargetEntry *) linitial(querytree->targetList))->expr;
/*
* If the function has any arguments declared as polymorphic types, then
* it wasn't type-checked at definition time; must do so now. (This will
* Make sure the function (still) returns what it's declared to. This will
* raise an error if wrong, but that's okay since the function would fail
* at runtime anyway. Note we do not try this until we have verified that
* no rewriting was needed; that's probably not important, but let's be
* careful.)
* careful.
*/
if (polymorphic)
(void) check_sql_fn_retval(funcid, result_type, querytree_list, NULL);
(void) check_sql_fn_retval(funcid, result_type, querytree_list, NULL);
/*
* Additional validity checks on the expression. It mustn't return a set,