Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b5eebc1

Browse files
committed
Centralize code for interpreting schema references, which had gotten
copied more places than I first thought it would. This fixes a bug: a couple of these places were neglecting to enforce USAGE access on explicitly-referenced schemas.
1 parent 7b970bc commit b5eebc1

File tree

6 files changed

+99
-223
lines changed

6 files changed

+99
-223
lines changed

src/backend/catalog/namespace.c

Lines changed: 69 additions & 100 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-
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.26 2002/07/20 05:16:56 momjian Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.27 2002/07/29 23:46:35 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -164,18 +164,7 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
164164
if (relation->schemaname)
165165
{
166166
/* use exact schema given */
167-
AclResult aclresult;
168-
169-
namespaceId = GetSysCacheOid(NAMESPACENAME,
170-
CStringGetDatum(relation->schemaname),
171-
0, 0, 0);
172-
if (!OidIsValid(namespaceId))
173-
elog(ERROR, "Namespace \"%s\" does not exist",
174-
relation->schemaname);
175-
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
176-
if (aclresult != ACLCHECK_OK)
177-
aclcheck_error(aclresult, relation->schemaname);
178-
167+
namespaceId = LookupExplicitNamespace(relation->schemaname);
179168
relId = get_relname_relid(relation->relname, namespaceId);
180169
}
181170
else
@@ -239,6 +228,7 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
239228
if (!OidIsValid(namespaceId))
240229
elog(ERROR, "Namespace \"%s\" does not exist",
241230
newRelation->schemaname);
231+
/* we do not check for USAGE rights here! */
242232
}
243233
else
244234
{
@@ -431,53 +421,19 @@ FuncCandidateList
431421
FuncnameGetCandidates(List *names, int nargs)
432422
{
433423
FuncCandidateList resultList = NULL;
434-
char *catalogname;
435-
char *schemaname = NULL;
436-
char *funcname = NULL;
424+
char *schemaname;
425+
char *funcname;
437426
Oid namespaceId;
438427
CatCList *catlist;
439428
int i;
440429

441430
/* deconstruct the name list */
442-
switch (length(names))
443-
{
444-
case 1:
445-
funcname = strVal(lfirst(names));
446-
break;
447-
case 2:
448-
schemaname = strVal(lfirst(names));
449-
funcname = strVal(lsecond(names));
450-
break;
451-
case 3:
452-
catalogname = strVal(lfirst(names));
453-
schemaname = strVal(lsecond(names));
454-
funcname = strVal(lfirst(lnext(lnext(names))));
455-
/*
456-
* We check the catalog name and then ignore it.
457-
*/
458-
if (strcmp(catalogname, DatabaseName) != 0)
459-
elog(ERROR, "Cross-database references are not implemented");
460-
break;
461-
default:
462-
elog(ERROR, "Improper qualified name (too many dotted names): %s",
463-
NameListToString(names));
464-
break;
465-
}
431+
DeconstructQualifiedName(names, &schemaname, &funcname);
466432

467433
if (schemaname)
468434
{
469435
/* use exact schema given */
470-
AclResult aclresult;
471-
472-
namespaceId = GetSysCacheOid(NAMESPACENAME,
473-
CStringGetDatum(schemaname),
474-
0, 0, 0);
475-
if (!OidIsValid(namespaceId))
476-
elog(ERROR, "Namespace \"%s\" does not exist",
477-
schemaname);
478-
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
479-
if (aclresult != ACLCHECK_OK)
480-
aclcheck_error(aclresult, schemaname);
436+
namespaceId = LookupExplicitNamespace(schemaname);
481437
}
482438
else
483439
{
@@ -684,53 +640,19 @@ FuncCandidateList
684640
OpernameGetCandidates(List *names, char oprkind)
685641
{
686642
FuncCandidateList resultList = NULL;
687-
char *catalogname;
688-
char *schemaname = NULL;
689-
char *opername = NULL;
643+
char *schemaname;
644+
char *opername;
690645
Oid namespaceId;
691646
CatCList *catlist;
692647
int i;
693648

694649
/* deconstruct the name list */
695-
switch (length(names))
696-
{
697-
case 1:
698-
opername = strVal(lfirst(names));
699-
break;
700-
case 2:
701-
schemaname = strVal(lfirst(names));
702-
opername = strVal(lsecond(names));
703-
break;
704-
case 3:
705-
catalogname = strVal(lfirst(names));
706-
schemaname = strVal(lsecond(names));
707-
opername = strVal(lfirst(lnext(lnext(names))));
708-
/*
709-
* We check the catalog name and then ignore it.
710-
*/
711-
if (strcmp(catalogname, DatabaseName) != 0)
712-
elog(ERROR, "Cross-database references are not implemented");
713-
break;
714-
default:
715-
elog(ERROR, "Improper qualified name (too many dotted names): %s",
716-
NameListToString(names));
717-
break;
718-
}
650+
DeconstructQualifiedName(names, &schemaname, &opername);
719651

720652
if (schemaname)
721653
{
722654
/* use exact schema given */
723-
AclResult aclresult;
724-
725-
namespaceId = GetSysCacheOid(NAMESPACENAME,
726-
CStringGetDatum(schemaname),
727-
0, 0, 0);
728-
if (!OidIsValid(namespaceId))
729-
elog(ERROR, "Namespace \"%s\" does not exist",
730-
schemaname);
731-
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
732-
if (aclresult != ACLCHECK_OK)
733-
aclcheck_error(aclresult, schemaname);
655+
namespaceId = LookupExplicitNamespace(schemaname);
734656
}
735657
else
736658
{
@@ -1105,25 +1027,22 @@ OpclassIsVisible(Oid opcid)
11051027
return visible;
11061028
}
11071029

1108-
11091030
/*
1110-
* QualifiedNameGetCreationNamespace
1111-
* Given a possibly-qualified name for an object (in List-of-Values
1112-
* format), determine what namespace the object should be created in.
1113-
* Also extract and return the object name (last component of list).
1031+
* DeconstructQualifiedName
1032+
* Given a possibly-qualified name expressed as a list of String nodes,
1033+
* extract the schema name and object name.
11141034
*
1115-
* This is *not* used for tables. Hence, the TEMP table namespace is
1116-
* never selected as the creation target.
1035+
* *nspname_p is set to NULL if there is no explicit schema name.
11171036
*/
1118-
Oid
1119-
QualifiedNameGetCreationNamespace(List *names, char **objname_p)
1037+
void
1038+
DeconstructQualifiedName(List *names,
1039+
char **nspname_p,
1040+
char **objname_p)
11201041
{
11211042
char *catalogname;
11221043
char *schemaname = NULL;
11231044
char *objname = NULL;
1124-
Oid namespaceId;
11251045

1126-
/* deconstruct the name list */
11271046
switch (length(names))
11281047
{
11291048
case 1:
@@ -1149,6 +1068,55 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
11491068
break;
11501069
}
11511070

1071+
*nspname_p = schemaname;
1072+
*objname_p = objname;
1073+
}
1074+
1075+
/*
1076+
* LookupExplicitNamespace
1077+
* Process an explicitly-specified schema name: look up the schema
1078+
* and verify we have USAGE (lookup) rights in it.
1079+
*
1080+
* Returns the namespace OID. Raises elog if any problem.
1081+
*/
1082+
Oid
1083+
LookupExplicitNamespace(char *nspname)
1084+
{
1085+
Oid namespaceId;
1086+
AclResult aclresult;
1087+
1088+
namespaceId = GetSysCacheOid(NAMESPACENAME,
1089+
CStringGetDatum(nspname),
1090+
0, 0, 0);
1091+
if (!OidIsValid(namespaceId))
1092+
elog(ERROR, "Namespace \"%s\" does not exist", nspname);
1093+
1094+
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
1095+
if (aclresult != ACLCHECK_OK)
1096+
aclcheck_error(aclresult, nspname);
1097+
1098+
return namespaceId;
1099+
}
1100+
1101+
/*
1102+
* QualifiedNameGetCreationNamespace
1103+
* Given a possibly-qualified name for an object (in List-of-Values
1104+
* format), determine what namespace the object should be created in.
1105+
* Also extract and return the object name (last component of list).
1106+
*
1107+
* This is *not* used for tables. Hence, the TEMP table namespace is
1108+
* never selected as the creation target.
1109+
*/
1110+
Oid
1111+
QualifiedNameGetCreationNamespace(List *names, char **objname_p)
1112+
{
1113+
char *schemaname;
1114+
char *objname;
1115+
Oid namespaceId;
1116+
1117+
/* deconstruct the name list */
1118+
DeconstructQualifiedName(names, &schemaname, &objname);
1119+
11521120
if (schemaname)
11531121
{
11541122
/* use exact schema given */
@@ -1158,6 +1126,7 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
11581126
if (!OidIsValid(namespaceId))
11591127
elog(ERROR, "Namespace \"%s\" does not exist",
11601128
schemaname);
1129+
/* we do not check for USAGE rights here! */
11611130
}
11621131
else
11631132
{

src/backend/commands/comment.c

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.52 2002/07/20 05:16:57 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.53 2002/07/29 23:46:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -22,7 +22,6 @@
2222
#include "catalog/pg_constraint.h"
2323
#include "catalog/pg_database.h"
2424
#include "catalog/pg_description.h"
25-
#include "catalog/pg_namespace.h"
2625
#include "catalog/pg_operator.h"
2726
#include "catalog/pg_rewrite.h"
2827
#include "catalog/pg_trigger.h"
@@ -468,36 +467,28 @@ CommentNamespace(List *qualname, char *comment)
468467
{
469468
Oid oid;
470469
Oid classoid;
471-
HeapTuple tp;
472470
char *namespace;
473471

474472
if (length(qualname) != 1)
475473
elog(ERROR, "CommentSchema: schema name may not be qualified");
476474
namespace = strVal(lfirst(qualname));
477475

478-
tp = SearchSysCache(NAMESPACENAME,
479-
CStringGetDatum(namespace),
480-
0, 0, 0);
481-
if (!HeapTupleIsValid(tp))
476+
oid = GetSysCacheOid(NAMESPACENAME,
477+
CStringGetDatum(namespace),
478+
0, 0, 0);
479+
if (!OidIsValid(oid))
482480
elog(ERROR, "CommentSchema: Schema \"%s\" could not be found",
483481
namespace);
484482

485-
/* no TupleDesc here to Assert(...->tdhasoid); */
486-
oid = HeapTupleGetOid(tp);
487-
488483
/* Check object security */
489484
if (!pg_namespace_ownercheck(oid, GetUserId()))
490485
aclcheck_error(ACLCHECK_NOT_OWNER, namespace);
491486

492487
/* pg_namespace doesn't have a hard-coded OID, so must look it up */
493-
classoid = get_relname_relid(NamespaceRelationName, PG_CATALOG_NAMESPACE);
494-
Assert(OidIsValid(classoid));
488+
classoid = get_system_catalog_relid(NamespaceRelationName);
495489

496490
/* Call CreateComments() to create/drop the comments */
497491
CreateComments(oid, classoid, 0, comment);
498-
499-
/* Cleanup */
500-
ReleaseSysCache(tp);
501492
}
502493

503494
/*
@@ -607,8 +598,7 @@ CommentRule(List *qualname, char *comment)
607598
aclcheck_error(aclcheck, rulename);
608599

609600
/* pg_rewrite doesn't have a hard-coded OID, so must look it up */
610-
classoid = get_relname_relid(RewriteRelationName, PG_CATALOG_NAMESPACE);
611-
Assert(OidIsValid(classoid));
601+
classoid = get_system_catalog_relid(RewriteRelationName);
612602

613603
/* Call CreateComments() to create/drop the comments */
614604

@@ -740,8 +730,7 @@ CommentOperator(List *opername, List *arguments, char *comment)
740730
aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(opername));
741731

742732
/* pg_operator doesn't have a hard-coded OID, so must look it up */
743-
classoid = get_relname_relid(OperatorRelationName, PG_CATALOG_NAMESPACE);
744-
Assert(OidIsValid(classoid));
733+
classoid = get_system_catalog_relid(OperatorRelationName);
745734

746735
/* Call CreateComments() to create/drop the comments */
747736
CreateComments(oid, classoid, 0, comment);

src/backend/commands/indexcmds.c

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.78 2002/07/20 05:16:57 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.79 2002/07/29 23:46:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -410,9 +410,8 @@ static Oid
410410
GetAttrOpClass(IndexElem *attribute, Oid attrType,
411411
char *accessMethodName, Oid accessMethodId)
412412
{
413-
char *catalogname;
414-
char *schemaname = NULL;
415-
char *opcname = NULL;
413+
char *schemaname;
414+
char *opcname;
416415
HeapTuple tuple;
417416
Oid opClassId,
418417
opInputType;
@@ -434,42 +433,14 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
434433
*/
435434

436435
/* deconstruct the name list */
437-
switch (length(attribute->opclass))
438-
{
439-
case 1:
440-
opcname = strVal(lfirst(attribute->opclass));
441-
break;
442-
case 2:
443-
schemaname = strVal(lfirst(attribute->opclass));
444-
opcname = strVal(lsecond(attribute->opclass));
445-
break;
446-
case 3:
447-
catalogname = strVal(lfirst(attribute->opclass));
448-
schemaname = strVal(lsecond(attribute->opclass));
449-
opcname = strVal(lfirst(lnext(lnext(attribute->opclass))));
450-
/*
451-
* We check the catalog name and then ignore it.
452-
*/
453-
if (strcmp(catalogname, DatabaseName) != 0)
454-
elog(ERROR, "Cross-database references are not implemented");
455-
break;
456-
default:
457-
elog(ERROR, "Improper opclass name (too many dotted names): %s",
458-
NameListToString(attribute->opclass));
459-
break;
460-
}
436+
DeconstructQualifiedName(attribute->opclass, &schemaname, &opcname);
461437

462438
if (schemaname)
463439
{
464440
/* Look in specific schema only */
465441
Oid namespaceId;
466442

467-
namespaceId = GetSysCacheOid(NAMESPACENAME,
468-
CStringGetDatum(schemaname),
469-
0, 0, 0);
470-
if (!OidIsValid(namespaceId))
471-
elog(ERROR, "Namespace \"%s\" does not exist",
472-
schemaname);
443+
namespaceId = LookupExplicitNamespace(schemaname);
473444
tuple = SearchSysCache(CLAAMNAMENSP,
474445
ObjectIdGetDatum(accessMethodId),
475446
PointerGetDatum(opcname),

0 commit comments

Comments
 (0)