Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf8eb75b

Browse files
committed
Repair insufficiently careful type checking for SQL-language functions:
we should check that the function code returns the claimed result datatypeevery time we parse the function for execution. Formerly, for simplescalar result types we assumed the creation-time check was sufficient, butthis fails if the function selects from a table that's been redefined sincethen, and even more obviously fails if check_function_bodies had been OFF.This is a significant security hole: not only can one trivially crash thebackend, but with appropriate misuse of pass-by-reference datatypes it ispossible to read out arbitrary locations in the server process's memory,which could allow retrieving database content the user should not be ableto see. Our thanks to Jeff Trout for the initial report.Security:CVE-2007-0555
1 parentdc4c26c commitf8eb75b

File tree

2 files changed

+29
-57
lines changed

2 files changed

+29
-57
lines changed

‎src/backend/executor/functions.c

Lines changed: 25 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.109 2007/01/05 22:19:27 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.110 2007/02/02 00:02:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -61,7 +61,7 @@ typedef struct
6161
{
6262
Oid*argtypes;/* resolved types of arguments */
6363
Oidrettype;/* actual return type */
64-
inttyplen;/* length of the return type */
64+
int16typlen;/* length of the return type */
6565
booltypbyval;/* true if return type is pass by value */
6666
boolreturnsTuple;/* true if returning whole tuple result */
6767
boolshutdown_reg;/* true if registered shutdown callback */
@@ -151,12 +151,9 @@ init_sql_fcache(FmgrInfo *finfo)
151151
Oidfoid=finfo->fn_oid;
152152
Oidrettype;
153153
HeapTupleprocedureTuple;
154-
HeapTupletypeTuple;
155154
Form_pg_procprocedureStruct;
156-
Form_pg_typetypeStruct;
157155
SQLFunctionCachePtrfcache;
158156
Oid*argOidVect;
159-
boolhaspolyarg;
160157
char*src;
161158
intnargs;
162159
List*queryTree_list;
@@ -193,35 +190,17 @@ init_sql_fcache(FmgrInfo *finfo)
193190

194191
fcache->rettype=rettype;
195192

193+
/* Fetch the typlen and byval info for the result type */
194+
get_typlenbyval(rettype,&fcache->typlen,&fcache->typbyval);
195+
196196
/* Remember if function is STABLE/IMMUTABLE */
197197
fcache->readonly_func=
198198
(procedureStruct->provolatile!=PROVOLATILE_VOLATILE);
199199

200-
/* Now look up the actual result type */
201-
typeTuple=SearchSysCache(TYPEOID,
202-
ObjectIdGetDatum(rettype),
203-
0,0,0);
204-
if (!HeapTupleIsValid(typeTuple))
205-
elog(ERROR,"cache lookup failed for type %u",rettype);
206-
typeStruct= (Form_pg_type)GETSTRUCT(typeTuple);
207-
208-
/*
209-
* get the type length and by-value flag from the type tuple; also do a
210-
* preliminary check for returnsTuple (this may prove inaccurate, see
211-
* below).
212-
*/
213-
fcache->typlen=typeStruct->typlen;
214-
fcache->typbyval=typeStruct->typbyval;
215-
fcache->returnsTuple= (typeStruct->typtype=='c'||
216-
rettype==RECORDOID);
217-
218200
/*
219-
* Parse and rewrite the queries. We need the argument type info to pass
220-
* to the parser.
201+
* We need the actual argument types to pass to the parser.
221202
*/
222203
nargs=procedureStruct->pronargs;
223-
haspolyarg= false;
224-
225204
if (nargs>0)
226205
{
227206
intargnum;
@@ -244,14 +223,16 @@ init_sql_fcache(FmgrInfo *finfo)
244223
errmsg("could not determine actual type of argument declared %s",
245224
format_type_be(argOidVect[argnum]))));
246225
argOidVect[argnum]=argtype;
247-
haspolyarg= true;
248226
}
249227
}
250228
}
251229
else
252230
argOidVect=NULL;
253231
fcache->argtypes=argOidVect;
254232

233+
/*
234+
* Parse and rewrite the queries in the function text.
235+
*/
255236
tmp=SysCacheGetAttr(PROCOID,
256237
procedureTuple,
257238
Anum_pg_proc_prosrc,
@@ -263,32 +244,32 @@ init_sql_fcache(FmgrInfo *finfo)
263244
queryTree_list=pg_parse_and_rewrite(src,argOidVect,nargs);
264245

265246
/*
266-
* If the function has any arguments declared as polymorphic types, then
267-
* it wasn't type-checked at definition time; must do so now.
247+
* Check that the function returns the type it claims to. Although
248+
* in simple cases this was already done when the function was defined,
249+
* we have to recheck because database objects used in the function's
250+
* queries might have changed type. We'd have to do it anyway if the
251+
* function had any polymorphic arguments.
268252
*
269-
* Also, force a type-check if the declared return type is a rowtype; we
270-
* need to find out whether we are actually returning the whole tuple
271-
* result, or just regurgitating a rowtype expression result. In the
253+
* Note: we set fcache->returnsTuple according to whether we are
254+
* returning the whole tuple result or just a single column. In the
272255
* latter case we clear returnsTuple because we need not act different
273-
* from the scalar result case.
256+
* from the scalar result case, even if it's a rowtype column.
274257
*
275258
* In the returnsTuple case, check_sql_fn_retval will also construct a
276259
* JunkFilter we can use to coerce the returned rowtype to the desired
277260
* form.
278261
*/
279-
if (haspolyarg||fcache->returnsTuple)
280-
fcache->returnsTuple=check_sql_fn_retval(foid,
281-
rettype,
282-
queryTree_list,
283-
&fcache->junkFilter);
262+
fcache->returnsTuple=check_sql_fn_retval(foid,
263+
rettype,
264+
queryTree_list,
265+
&fcache->junkFilter);
284266

285267
/* Finally, plan the queries */
286268
fcache->func_state=init_execution_state(queryTree_list,
287269
fcache->readonly_func);
288270

289271
pfree(src);
290272

291-
ReleaseSysCache(typeTuple);
292273
ReleaseSysCache(procedureTuple);
293274

294275
finfo->fn_extra= (void*)fcache;
@@ -858,11 +839,10 @@ ShutdownSQLFunction(Datum arg)
858839
* the final query in the function. We do some ad-hoc type checking here
859840
* to be sure that the user is returning the type he claims.
860841
*
861-
* This is normally applied during function definition, but in the case
862-
* of a function with polymorphic arguments, we instead apply it during
863-
* function execution startup.The rettype is then the actual resolved
864-
* output type of the function, rather than the declared type.(Therefore,
865-
* we should never see ANYARRAY or ANYELEMENT as rettype.)
842+
* For a polymorphic function the passed rettype must be the actual resolved
843+
* output type of the function; we should never see ANYARRAY or ANYELEMENT
844+
* as rettype. (This means we can't check the type during function definition
845+
* of a polymorphic function.)
866846
*
867847
* The return value is true if the function returns the entire tuple result
868848
* of its final SELECT, and false otherwise. Note that because we allow

‎src/backend/optimizer/util/clauses.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.232 2007/02/01 19:10:26 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.233 2007/02/02 00:02:55 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHORDATEMAJOR EVENT
@@ -2751,7 +2751,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
27512751
eval_const_expressions_context*context)
27522752
{
27532753
Form_pg_procfuncform= (Form_pg_proc)GETSTRUCT(func_tuple);
2754-
boolpolymorphic= false;
27552754
Oid*argtypes;
27562755
char*src;
27572756
Datumtmp;
@@ -2814,15 +2813,10 @@ inline_function(Oid funcid, Oid result_type, List *args,
28142813
if (argtypes[i]==ANYARRAYOID||
28152814
argtypes[i]==ANYELEMENTOID)
28162815
{
2817-
polymorphic= true;
28182816
argtypes[i]=exprType((Node*)list_nth(args,i));
28192817
}
28202818
}
28212819

2822-
if (funcform->prorettype==ANYARRAYOID||
2823-
funcform->prorettype==ANYELEMENTOID)
2824-
polymorphic= true;
2825-
28262820
/* Fetch and parse the function body */
28272821
tmp=SysCacheGetAttr(PROCOID,
28282822
func_tuple,
@@ -2874,15 +2868,13 @@ inline_function(Oid funcid, Oid result_type, List *args,
28742868
newexpr= (Node*) ((TargetEntry*)linitial(querytree->targetList))->expr;
28752869

28762870
/*
2877-
* If the function has any arguments declared as polymorphic types, then
2878-
* it wasn't type-checked at definition time; must do so now. (This will
2871+
* Make sure the function (still) returns what it's declared to. This will
28792872
* raise an error if wrong, but that's okay since the function would fail
28802873
* at runtime anyway. Note we do not try this until we have verified that
28812874
* no rewriting was needed; that's probably not important, but let's be
2882-
* careful.)
2875+
* careful.
28832876
*/
2884-
if (polymorphic)
2885-
(void)check_sql_fn_retval(funcid,result_type,querytree_list,NULL);
2877+
(void)check_sql_fn_retval(funcid,result_type,querytree_list,NULL);
28862878

28872879
/*
28882880
* Additional validity checks on the expression. It mustn't return a set,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp