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

Commit862861e

Browse files
committed
Fix a couple of misbehaviors rooted in the fact that the default creation
namespace isn't necessarily first in the search path (there could be implicitschemas ahead of it). Examples aretest=# set search_path TO s1;test=# create view pg_timezone_names as select * from pg_timezone_names();ERROR: "pg_timezone_names" is already a viewtest=# create table pg_class (f1 int primary key);ERROR: permission denied: "pg_class" is a system catalogYou'd expect these commands to create the requested objects in s1, sincenames beginning with pg_ aren't supposed to be reserved anymore. What ishappening is that we create the requested base table and then executeadditional commands (here, CREATE RULE or CREATE INDEX), and that code ispassed the same RangeVar that was in the original command. Since thatRangeVar has schemaname = NULL, the secondary commands think they should do apath search, and that means they find system catalogs that are implicitly infront of s1 in the search path.This is perilously close to being a security hole: if the secondary commandfailed to apply a permission check then it'd be possible for unprivilegedusers to make schema modifications to system catalogs. But as far as I canfind, there is no code path in which a check doesn't occur. Which makes itjust a weird corner-case bug for people who are silly enough to want toname their tables the same as a system catalog.The relevant code has changed quite a bit since 8.2, which means this patchwouldn't work as-is in the back branches. Since it's a corner case no onehas reported from the field, I'm not going to bother trying to back-patch.
1 parent6c96188 commit862861e

File tree

5 files changed

+66
-27
lines changed

5 files changed

+66
-27
lines changed

‎src/backend/catalog/namespace.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.98 2007/08/21 01:11:13 tgl Exp $
16+
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.99 2007/08/27 03:36:08 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -228,7 +228,26 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
228228
relation->relname)));
229229
}
230230

231-
if (relation->schemaname)
231+
/*
232+
* If istemp is set, this is a reference to a temp relation. The parser
233+
* never generates such a RangeVar in simple DML, but it can happen in
234+
* contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY KEY)". Such a
235+
* command will generate an added CREATE INDEX operation, which must be
236+
* careful to find the temp table, even when pg_temp is not first in the
237+
* search path.
238+
*/
239+
if (relation->istemp)
240+
{
241+
if (relation->schemaname)
242+
ereport(ERROR,
243+
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
244+
errmsg("temporary tables cannot specify a schema name")));
245+
if (OidIsValid(myTempNamespace))
246+
relId=get_relname_relid(relation->relname,myTempNamespace);
247+
else/* this probably can't happen? */
248+
relId=InvalidOid;
249+
}
250+
elseif (relation->schemaname)
232251
{
233252
/* use exact schema given */
234253
namespaceId=LookupExplicitNamespace(relation->schemaname);

‎src/backend/commands/view.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.101 2007/06/23 22:12:50 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.102 2007/08/27 03:36:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -260,14 +260,14 @@ checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc)
260260
}
261261

262262
staticvoid
263-
DefineViewRules(constRangeVar*view,Query*viewParse,boolreplace)
263+
DefineViewRules(OidviewOid,Query*viewParse,boolreplace)
264264
{
265265
/*
266266
* Set up the ON SELECT rule. Since the query has already been through
267267
* parse analysis, we use DefineQueryRewrite() directly.
268268
*/
269269
DefineQueryRewrite(pstrdup(ViewSelectRuleName),
270-
(RangeVar*)copyObject((RangeVar*)view),
270+
viewOid,
271271
NULL,
272272
CMD_SELECT,
273273
true,
@@ -404,7 +404,9 @@ DefineView(ViewStmt *stmt, const char *queryString)
404404

405405
/*
406406
* If the user didn't explicitly ask for a temporary view, check whether
407-
* we need one implicitly.
407+
* we need one implicitly. We allow TEMP to be inserted automatically
408+
* as long as the CREATE command is consistent with that --- no explicit
409+
* schema name.
408410
*/
409411
view=stmt->view;
410412
if (!view->istemp&&isViewOnTempTable(viewParse))
@@ -441,7 +443,7 @@ DefineView(ViewStmt *stmt, const char *queryString)
441443
/*
442444
* Now create the rules associated with the view.
443445
*/
444-
DefineViewRules(view,viewParse,stmt->replace);
446+
DefineViewRules(viewOid,viewParse,stmt->replace);
445447
}
446448

447449
/*

‎src/backend/parser/parse_utilcmd.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
2020
* Portions Copyright (c) 1994, Regents of the University of California
2121
*
22-
*$PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.2 2007/07/17 05:02:02 neilc Exp $
22+
*$PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.3 2007/08/27 03:36:08 tgl Exp $
2323
*
2424
*-------------------------------------------------------------------------
2525
*/
@@ -143,6 +143,20 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
143143
*/
144144
stmt= (CreateStmt*)copyObject(stmt);
145145

146+
/*
147+
* If the target relation name isn't schema-qualified, make it so. This
148+
* prevents some corner cases in which added-on rewritten commands might
149+
* think they should apply to other relations that have the same name
150+
* and are earlier in the search path. "istemp" is equivalent to a
151+
* specification of pg_temp, so no need for anything extra in that case.
152+
*/
153+
if (stmt->relation->schemaname==NULL&& !stmt->relation->istemp)
154+
{
155+
Oidnamespaceid=RangeVarGetCreationNamespace(stmt->relation);
156+
157+
stmt->relation->schemaname=get_namespace_name(namespaceid);
158+
}
159+
146160
/* Set up pstate */
147161
pstate=make_parsestate(NULL);
148162
pstate->p_sourcetext=queryString;

‎src/backend/rewrite/rewriteDefine.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.121 2007/06/23 22:12:51 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.122 2007/08/27 03:36:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -17,6 +17,7 @@
1717
#include"access/heapam.h"
1818
#include"catalog/dependency.h"
1919
#include"catalog/indexing.h"
20+
#include"catalog/namespace.h"
2021
#include"catalog/pg_rewrite.h"
2122
#include"miscadmin.h"
2223
#include"optimizer/clauses.h"
@@ -189,13 +190,17 @@ DefineRule(RuleStmt *stmt, const char *queryString)
189190
{
190191
List*actions;
191192
Node*whereClause;
193+
OidrelId;
192194

193195
/* Parse analysis ... */
194196
transformRuleStmt(stmt,queryString,&actions,&whereClause);
195197

196-
/* ... and execution */
198+
/* ... find the relation ... */
199+
relId=RangeVarGetRelid(stmt->relation, false);
200+
201+
/* ... and execute */
197202
DefineQueryRewrite(stmt->rulename,
198-
stmt->relation,
203+
relId,
199204
whereClause,
200205
stmt->event,
201206
stmt->instead,
@@ -213,15 +218,14 @@ DefineRule(RuleStmt *stmt, const char *queryString)
213218
*/
214219
void
215220
DefineQueryRewrite(char*rulename,
216-
RangeVar*event_obj,
221+
Oidevent_relid,
217222
Node*event_qual,
218223
CmdTypeevent_type,
219224
boolis_instead,
220225
boolreplace,
221226
List*action)
222227
{
223228
Relationevent_relation;
224-
Oidev_relid;
225229
OidruleId;
226230
intevent_attno;
227231
ListCell*l;
@@ -235,13 +239,12 @@ DefineQueryRewrite(char *rulename,
235239
* grab ShareLock to lock out insert/update/delete actions. But for now,
236240
* let's just grab AccessExclusiveLock all the time.
237241
*/
238-
event_relation=heap_openrv(event_obj,AccessExclusiveLock);
239-
ev_relid=RelationGetRelid(event_relation);
242+
event_relation=heap_open(event_relid,AccessExclusiveLock);
240243

241244
/*
242245
* Check user has permission to apply rules to this relation.
243246
*/
244-
if (!pg_class_ownercheck(ev_relid,GetUserId()))
247+
if (!pg_class_ownercheck(event_relid,GetUserId()))
245248
aclcheck_error(ACLCHECK_NOT_OWNER,ACL_KIND_CLASS,
246249
RelationGetRelationName(event_relation));
247250

@@ -352,12 +355,13 @@ DefineQueryRewrite(char *rulename,
352355
* truncated.
353356
*/
354357
if (strncmp(rulename,"_RET",4)!=0||
355-
strncmp(rulename+4,event_obj->relname,
358+
strncmp(rulename+4,RelationGetRelationName(event_relation),
356359
NAMEDATALEN-4-4)!=0)
357360
ereport(ERROR,
358361
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
359362
errmsg("view rule for \"%s\" must be named \"%s\"",
360-
event_obj->relname,ViewSelectRuleName)));
363+
RelationGetRelationName(event_relation),
364+
ViewSelectRuleName)));
361365
rulename=pstrdup(ViewSelectRuleName);
362366
}
363367

@@ -377,27 +381,27 @@ DefineQueryRewrite(char *rulename,
377381
ereport(ERROR,
378382
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
379383
errmsg("could not convert table \"%s\" to a view because it is not empty",
380-
event_obj->relname)));
384+
RelationGetRelationName(event_relation))));
381385
heap_endscan(scanDesc);
382386

383387
if (event_relation->rd_rel->reltriggers!=0)
384388
ereport(ERROR,
385389
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
386390
errmsg("could not convert table \"%s\" to a view because it has triggers",
387-
event_obj->relname),
391+
RelationGetRelationName(event_relation)),
388392
errhint("In particular, the table cannot be involved in any foreign key relationships.")));
389393

390394
if (event_relation->rd_rel->relhasindex)
391395
ereport(ERROR,
392396
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
393397
errmsg("could not convert table \"%s\" to a view because it has indexes",
394-
event_obj->relname)));
398+
RelationGetRelationName(event_relation))));
395399

396400
if (event_relation->rd_rel->relhassubclass)
397401
ereport(ERROR,
398402
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
399403
errmsg("could not convert table \"%s\" to a view because it has child tables",
400-
event_obj->relname)));
404+
RelationGetRelationName(event_relation))));
401405

402406
RelisBecomingView= true;
403407
}
@@ -449,7 +453,7 @@ DefineQueryRewrite(char *rulename,
449453
{
450454
ruleId=InsertRule(rulename,
451455
event_type,
452-
ev_relid,
456+
event_relid,
453457
event_attno,
454458
is_instead,
455459
event_qual,
@@ -465,7 +469,7 @@ DefineQueryRewrite(char *rulename,
465469
* backends (including me!) to update relcache entries with the new
466470
* rule.
467471
*/
468-
SetRelationRuleStatus(ev_relid, true,RelisBecomingView);
472+
SetRelationRuleStatus(event_relid, true,RelisBecomingView);
469473
}
470474

471475
/*
@@ -701,7 +705,7 @@ EnableDisableRule(Relation rel, const char *rulename,
701705
/*
702706
* Rename an existing rewrite rule.
703707
*
704-
* This is unused code at the moment.
708+
* This is unused code at the moment. Note that it lacks a permissions check.
705709
*/
706710
#ifdefNOT_USED
707711
void

‎src/include/rewrite/rewriteDefine.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/rewrite/rewriteDefine.h,v 1.25 2007/03/19 23:38:32 wieck Exp $
10+
* $PostgreSQL: pgsql/src/include/rewrite/rewriteDefine.h,v 1.26 2007/08/27 03:36:08 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -24,7 +24,7 @@
2424
externvoidDefineRule(RuleStmt*stmt,constchar*queryString);
2525

2626
externvoidDefineQueryRewrite(char*rulename,
27-
RangeVar*event_obj,
27+
Oidevent_relid,
2828
Node*event_qual,
2929
CmdTypeevent_type,
3030
boolis_instead,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp