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

Commitb9ad73a

Browse files
committed
Fix crashes with CREATE SCHEMA AUTHORIZATION and schema elements
CREATE SCHEMA AUTHORIZATION with appended schema elements can lead tocrashes when comparing the schema name of the query with the schemasused in the qualification of some clauses in the elements' queries.The origin of the problem is that the transformation routine for theelements listed in a CREATE SCHEMA query uses as new, expected, schemaname the one listed in CreateSchemaStmt itself. However, depending onthe query, CreateSchemaStmt.schemaname may be NULL, being computedinstead from the role specification of the query given by theAUTHORIZATION clause, that could be either:- A user name string, with the new schema name being set to the samevalue as the role given.- Guessed from CURRENT_ROLE, SESSION_ROLE or CURRENT_ROLE, with a newschema name computed from the security context where CREATE SCHEMA isrunning.Regression tests are added for CREATE SCHEMA with some appended elements(some of them with schema qualifications), covering also some rolespecification patterns.While on it, this simplifies the context structure used during thetransformation of the elements listed in a CREATE SCHEMA query byremoving the fields for the role specification and the role type. Theywere not used, and for the role specification this could be confusing asthe schema name may by extracted from that at the beginning ofCreateSchemaCommand().This issue exists for a long time, so backpatch down to all the versionssupported.Reported-by: Song HongyuAuthor: Michael PaquierReviewed-by: Richard GuoDiscussion:https://postgr.es/m/17909-f65c12dfc5f0451d@postgresql.orgBackpatch-through: 11
1 parentc98b06e commitb9ad73a

File tree

6 files changed

+192
-22
lines changed

6 files changed

+192
-22
lines changed

‎src/backend/commands/schemacmds.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
178178
* we cannot, in general, run parse analysis on one statement until we
179179
* have actually executed the prior ones.
180180
*/
181-
parsetree_list=transformCreateSchemaStmt(stmt);
181+
parsetree_list=transformCreateSchemaStmtElements(stmt->schemaElts,
182+
schemaName);
182183

183184
/*
184185
* Execute each command contained in the CREATE SCHEMA. Since the grammar

‎src/backend/parser/parse_utilcmd.c

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,10 @@ typedef struct
9595
boolofType;/* true if statement contains OF typename */
9696
}CreateStmtContext;
9797

98-
/* State shared bytransformCreateSchemaStmt and its subroutines */
98+
/* State shared bytransformCreateSchemaStmtElements and its subroutines */
9999
typedefstruct
100100
{
101-
constchar*stmtType;/* "CREATE SCHEMA" or "ALTER SCHEMA" */
102-
char*schemaname;/* name of schema */
103-
RoleSpec*authrole;/* owner of schema */
101+
constchar*schemaname;/* name of schema */
104102
List*sequences;/* CREATE SEQUENCE items */
105103
List*tables;/* CREATE TABLE items */
106104
List*views;/* CREATE VIEW items */
@@ -134,7 +132,7 @@ static void transformCheckConstraints(CreateStmtContext *cxt,
134132
staticvoidtransformConstraintAttrs(CreateStmtContext*cxt,
135133
List*constraintList);
136134
staticvoidtransformColumnType(CreateStmtContext*cxt,ColumnDef*column);
137-
staticvoidsetSchemaName(char*context_schema,char**stmt_schema_name);
135+
staticvoidsetSchemaName(constchar*context_schema,char**stmt_schema_name);
138136
staticvoidtransformPartitionCmd(CreateStmtContext*cxt,PartitionCmd*cmd);
139137
staticList*transformPartitionRangeBounds(ParseState*pstate,List*blist,
140138
Relationparent);
@@ -3806,14 +3804,18 @@ transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
38063804

38073805

38083806
/*
3809-
*transformCreateSchemaStmt -
3810-
* analyzes the CREATE SCHEMA statement
3807+
*transformCreateSchemaStmtElements -
3808+
* analyzes theelements of aCREATE SCHEMA statement
38113809
*
3812-
* Split the schema element list into individual commands and place
3813-
* them in the result list in an order such that there are no forward
3814-
* references (e.g. GRANT to a table created later in the list). Note
3815-
* that the logic we use for determining forward references is
3816-
* presently quite incomplete.
3810+
* Split the schema element list from a CREATE SCHEMA statement into
3811+
* individual commands and place them in the result list in an order
3812+
* such that there are no forward references (e.g. GRANT to a table
3813+
* created later in the list). Note that the logic we use for determining
3814+
* forward references is presently quite incomplete.
3815+
*
3816+
* "schemaName" is the name of the schema that will be used for the creation
3817+
* of the objects listed, that may be compiled from the schema name defined
3818+
* in the statement or a role specification.
38173819
*
38183820
* SQL also allows constraints to make forward references, so thumb through
38193821
* the table columns and move forward references to a posterior alter-table
@@ -3829,15 +3831,13 @@ transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
38293831
* extent.
38303832
*/
38313833
List*
3832-
transformCreateSchemaStmt(CreateSchemaStmt*stmt)
3834+
transformCreateSchemaStmtElements(List*schemaElts,constchar*schemaName)
38333835
{
38343836
CreateSchemaStmtContextcxt;
38353837
List*result;
38363838
ListCell*elements;
38373839

3838-
cxt.stmtType="CREATE SCHEMA";
3839-
cxt.schemaname=stmt->schemaname;
3840-
cxt.authrole= (RoleSpec*)stmt->authrole;
3840+
cxt.schemaname=schemaName;
38413841
cxt.sequences=NIL;
38423842
cxt.tables=NIL;
38433843
cxt.views=NIL;
@@ -3849,7 +3849,7 @@ transformCreateSchemaStmt(CreateSchemaStmt *stmt)
38493849
* Run through each schema element in the schema element list. Separate
38503850
* statements by type, and do preliminary analysis.
38513851
*/
3852-
foreach(elements,stmt->schemaElts)
3852+
foreach(elements,schemaElts)
38533853
{
38543854
Node*element=lfirst(elements);
38553855

@@ -3934,10 +3934,10 @@ transformCreateSchemaStmt(CreateSchemaStmt *stmt)
39343934
*Set or check schema name in an element of a CREATE SCHEMA command
39353935
*/
39363936
staticvoid
3937-
setSchemaName(char*context_schema,char**stmt_schema_name)
3937+
setSchemaName(constchar*context_schema,char**stmt_schema_name)
39383938
{
39393939
if (*stmt_schema_name==NULL)
3940-
*stmt_schema_name=context_schema;
3940+
*stmt_schema_name=unconstify(char*,context_schema);
39413941
elseif (strcmp(context_schema,*stmt_schema_name)!=0)
39423942
ereport(ERROR,
39433943
(errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),

‎src/include/parser/parse_utilcmd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ extern CreateStatsStmt *transformStatsStmt(Oid relid, CreateStatsStmt *stmt,
3030
constchar*queryString);
3131
externvoidtransformRuleStmt(RuleStmt*stmt,constchar*queryString,
3232
List**actions,Node**whereClause);
33-
externList*transformCreateSchemaStmt(CreateSchemaStmt*stmt);
33+
externList*transformCreateSchemaStmtElements(List*schemaElts,
34+
constchar*schemaName);
3435
externPartitionBoundSpec*transformPartitionBound(ParseState*pstate,Relationparent,
3536
PartitionBoundSpec*spec);
3637
externList*expandTableLikeClause(RangeVar*heapRel,
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
--
2+
-- CREATE_SCHEMA
3+
--
4+
-- Schema creation with elements.
5+
CREATE ROLE regress_create_schema_role SUPERUSER;
6+
-- Cases where schema creation fails as objects are qualified with a schema
7+
-- that does not match with what's expected.
8+
-- This checks all the object types that include schema qualifications.
9+
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
10+
CREATE SEQUENCE schema_not_existing.seq;
11+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
12+
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
13+
CREATE TABLE schema_not_existing.tab (id int);
14+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
15+
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
16+
CREATE VIEW schema_not_existing.view AS SELECT 1;
17+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
18+
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
19+
CREATE INDEX ON schema_not_existing.tab (id);
20+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
21+
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
22+
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
23+
EXECUTE FUNCTION schema_trig.no_func();
24+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
25+
-- Again, with a role specification and no schema names.
26+
SET ROLE regress_create_schema_role;
27+
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
28+
CREATE SEQUENCE schema_not_existing.seq;
29+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
30+
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
31+
CREATE TABLE schema_not_existing.tab (id int);
32+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
33+
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
34+
CREATE VIEW schema_not_existing.view AS SELECT 1;
35+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
36+
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
37+
CREATE INDEX ON schema_not_existing.tab (id);
38+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
39+
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
40+
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
41+
EXECUTE FUNCTION schema_trig.no_func();
42+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
43+
-- Again, with a schema name and a role specification.
44+
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
45+
CREATE SEQUENCE schema_not_existing.seq;
46+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
47+
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
48+
CREATE TABLE schema_not_existing.tab (id int);
49+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
50+
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
51+
CREATE VIEW schema_not_existing.view AS SELECT 1;
52+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
53+
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
54+
CREATE INDEX ON schema_not_existing.tab (id);
55+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
56+
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
57+
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
58+
EXECUTE FUNCTION schema_trig.no_func();
59+
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
60+
RESET ROLE;
61+
-- Cases where the schema creation succeeds.
62+
-- The schema created matches the role name.
63+
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
64+
CREATE TABLE regress_create_schema_role.tab (id int);
65+
\d regress_create_schema_role.tab
66+
Table "regress_create_schema_role.tab"
67+
Column | Type | Collation | Nullable | Default
68+
--------+---------+-----------+----------+---------
69+
id | integer | | |
70+
71+
DROP SCHEMA regress_create_schema_role CASCADE;
72+
NOTICE: drop cascades to table regress_create_schema_role.tab
73+
-- Again, with a different role specification and no schema names.
74+
SET ROLE regress_create_schema_role;
75+
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
76+
CREATE TABLE regress_create_schema_role.tab (id int);
77+
\d regress_create_schema_role.tab
78+
Table "regress_create_schema_role.tab"
79+
Column | Type | Collation | Nullable | Default
80+
--------+---------+-----------+----------+---------
81+
id | integer | | |
82+
83+
DROP SCHEMA regress_create_schema_role CASCADE;
84+
NOTICE: drop cascades to table tab
85+
-- Again, with a schema name and a role specification.
86+
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
87+
CREATE TABLE regress_schema_1.tab (id int);
88+
\d regress_schema_1.tab
89+
Table "regress_schema_1.tab"
90+
Column | Type | Collation | Nullable | Default
91+
--------+---------+-----------+----------+---------
92+
id | integer | | |
93+
94+
DROP SCHEMA regress_schema_1 CASCADE;
95+
NOTICE: drop cascades to table regress_schema_1.tab
96+
RESET ROLE;
97+
-- Clean up
98+
DROP ROLE regress_create_schema_role;

‎src/test/regress/parallel_schedule

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ test: copy copyselect copydml insert insert_conflict
4747
# More groups of parallel tests
4848
# Note: many of the tests in later groups depend on create_index
4949
# ----------
50-
test: create_function_c create_misc create_operator create_procedure create_table create_type
50+
test: create_function_c create_misc create_operator create_procedure create_table create_type create_schema
5151
test: create_index create_index_spgist create_view index_including index_including_gist
5252

5353
# ----------
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
--
2+
-- CREATE_SCHEMA
3+
--
4+
5+
-- Schema creation with elements.
6+
7+
CREATE ROLE regress_create_schema_role SUPERUSER;
8+
9+
-- Cases where schema creation fails as objects are qualified with a schema
10+
-- that does not match with what's expected.
11+
-- This checks all the object types that include schema qualifications.
12+
CREATESCHEMAAUTHORIZATION regress_create_schema_role
13+
CREATESEQUENCEschema_not_existing.seq;
14+
CREATESCHEMAAUTHORIZATION regress_create_schema_role
15+
CREATETABLEschema_not_existing.tab (idint);
16+
CREATESCHEMAAUTHORIZATION regress_create_schema_role
17+
CREATEVIEWschema_not_existing.viewASSELECT1;
18+
CREATESCHEMAAUTHORIZATION regress_create_schema_role
19+
CREATEINDEXONschema_not_existing.tab (id);
20+
CREATESCHEMAAUTHORIZATION regress_create_schema_role
21+
CREATETRIGGERschema_trig BEFORE INSERTONschema_not_existing.tab
22+
EXECUTE FUNCTIONschema_trig.no_func();
23+
-- Again, with a role specification and no schema names.
24+
SET ROLE regress_create_schema_role;
25+
CREATESCHEMAAUTHORIZATION CURRENT_ROLE
26+
CREATESEQUENCEschema_not_existing.seq;
27+
CREATESCHEMAAUTHORIZATION CURRENT_ROLE
28+
CREATETABLEschema_not_existing.tab (idint);
29+
CREATESCHEMAAUTHORIZATION CURRENT_ROLE
30+
CREATEVIEWschema_not_existing.viewASSELECT1;
31+
CREATESCHEMAAUTHORIZATION CURRENT_ROLE
32+
CREATEINDEXONschema_not_existing.tab (id);
33+
CREATESCHEMAAUTHORIZATION CURRENT_ROLE
34+
CREATETRIGGERschema_trig BEFORE INSERTONschema_not_existing.tab
35+
EXECUTE FUNCTIONschema_trig.no_func();
36+
-- Again, with a schema name and a role specification.
37+
CREATESCHEMAregress_schema_1 AUTHORIZATION CURRENT_ROLE
38+
CREATESEQUENCEschema_not_existing.seq;
39+
CREATESCHEMAregress_schema_1 AUTHORIZATION CURRENT_ROLE
40+
CREATETABLEschema_not_existing.tab (idint);
41+
CREATESCHEMAregress_schema_1 AUTHORIZATION CURRENT_ROLE
42+
CREATEVIEWschema_not_existing.viewASSELECT1;
43+
CREATESCHEMAregress_schema_1 AUTHORIZATION CURRENT_ROLE
44+
CREATEINDEXONschema_not_existing.tab (id);
45+
CREATESCHEMAregress_schema_1 AUTHORIZATION CURRENT_ROLE
46+
CREATETRIGGERschema_trig BEFORE INSERTONschema_not_existing.tab
47+
EXECUTE FUNCTIONschema_trig.no_func();
48+
RESET ROLE;
49+
50+
-- Cases where the schema creation succeeds.
51+
-- The schema created matches the role name.
52+
CREATESCHEMAAUTHORIZATION regress_create_schema_role
53+
CREATETABLEregress_create_schema_role.tab (idint);
54+
\dregress_create_schema_role.tab
55+
DROPSCHEMA regress_create_schema_role CASCADE;
56+
-- Again, with a different role specification and no schema names.
57+
SET ROLE regress_create_schema_role;
58+
CREATESCHEMAAUTHORIZATION CURRENT_ROLE
59+
CREATETABLEregress_create_schema_role.tab (idint);
60+
\dregress_create_schema_role.tab
61+
DROPSCHEMA regress_create_schema_role CASCADE;
62+
-- Again, with a schema name and a role specification.
63+
CREATESCHEMAregress_schema_1 AUTHORIZATION CURRENT_ROLE
64+
CREATETABLEregress_schema_1.tab (idint);
65+
\dregress_schema_1.tab
66+
DROPSCHEMA regress_schema_1 CASCADE;
67+
RESET ROLE;
68+
69+
-- Clean up
70+
DROP ROLE regress_create_schema_role;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp