mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Fix crashes with CREATE SCHEMA AUTHORIZATION and schema elements
CREATE SCHEMA AUTHORIZATION with appended schema elements can lead to crashes when comparing the schema name of the query with the schemas used in the qualification of some clauses in the elements' queries. The origin of the problem is that the transformation routine for the elements listed in a CREATE SCHEMA query uses as new, expected, schema name the one listed in CreateSchemaStmt itself. However, depending on the query, CreateSchemaStmt.schemaname may be NULL, being computed instead from the role specification of the query given by the AUTHORIZATION clause, that could be either: - A user name string, with the new schema name being set to the same value as the role given. - Guessed from CURRENT_ROLE, SESSION_ROLE or CURRENT_ROLE, with a new schema name computed from the security context where CREATE SCHEMA is running. Regression tests are added for CREATE SCHEMA with some appended elements (some of them with schema qualifications), covering also some role specification patterns. While on it, this simplifies the context structure used during the transformation of the elements listed in a CREATE SCHEMA query by removing the fields for the role specification and the role type. They were not used, and for the role specification this could be confusing as the schema name may by extracted from that at the beginning of CreateSchemaCommand(). This issue exists for a long time, so backpatch down to all the versions supported. Reported-by: Song Hongyu Author: Michael Paquier Reviewed-by: Richard Guo Discussion: https://postgr.es/m/17909-f65c12dfc5f0451d@postgresql.org Backpatch-through: 11
This commit is contained in:
98
src/test/regress/expected/create_schema.out
Normal file
98
src/test/regress/expected/create_schema.out
Normal file
@@ -0,0 +1,98 @@
|
||||
--
|
||||
-- CREATE_SCHEMA
|
||||
--
|
||||
-- Schema creation with elements.
|
||||
CREATE ROLE regress_create_schema_role SUPERUSER;
|
||||
-- Cases where schema creation fails as objects are qualified with a schema
|
||||
-- that does not match with what's expected.
|
||||
-- This checks all the object types that include schema qualifications.
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE SEQUENCE schema_not_existing.seq;
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE TABLE schema_not_existing.tab (id int);
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE VIEW schema_not_existing.view AS SELECT 1;
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE INDEX ON schema_not_existing.tab (id);
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
|
||||
EXECUTE FUNCTION schema_trig.no_func();
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
-- Again, with a role specification and no schema names.
|
||||
SET ROLE regress_create_schema_role;
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE SEQUENCE schema_not_existing.seq;
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TABLE schema_not_existing.tab (id int);
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE VIEW schema_not_existing.view AS SELECT 1;
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE INDEX ON schema_not_existing.tab (id);
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
|
||||
EXECUTE FUNCTION schema_trig.no_func();
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_create_schema_role)
|
||||
-- Again, with a schema name and a role specification.
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE SEQUENCE schema_not_existing.seq;
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TABLE schema_not_existing.tab (id int);
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE VIEW schema_not_existing.view AS SELECT 1;
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE INDEX ON schema_not_existing.tab (id);
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
|
||||
EXECUTE FUNCTION schema_trig.no_func();
|
||||
ERROR: CREATE specifies a schema (schema_not_existing) different from the one being created (regress_schema_1)
|
||||
RESET ROLE;
|
||||
-- Cases where the schema creation succeeds.
|
||||
-- The schema created matches the role name.
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE TABLE regress_create_schema_role.tab (id int);
|
||||
\d regress_create_schema_role.tab
|
||||
Table "regress_create_schema_role.tab"
|
||||
Column | Type | Collation | Nullable | Default
|
||||
--------+---------+-----------+----------+---------
|
||||
id | integer | | |
|
||||
|
||||
DROP SCHEMA regress_create_schema_role CASCADE;
|
||||
NOTICE: drop cascades to table regress_create_schema_role.tab
|
||||
-- Again, with a different role specification and no schema names.
|
||||
SET ROLE regress_create_schema_role;
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TABLE regress_create_schema_role.tab (id int);
|
||||
\d regress_create_schema_role.tab
|
||||
Table "regress_create_schema_role.tab"
|
||||
Column | Type | Collation | Nullable | Default
|
||||
--------+---------+-----------+----------+---------
|
||||
id | integer | | |
|
||||
|
||||
DROP SCHEMA regress_create_schema_role CASCADE;
|
||||
NOTICE: drop cascades to table tab
|
||||
-- Again, with a schema name and a role specification.
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TABLE regress_schema_1.tab (id int);
|
||||
\d regress_schema_1.tab
|
||||
Table "regress_schema_1.tab"
|
||||
Column | Type | Collation | Nullable | Default
|
||||
--------+---------+-----------+----------+---------
|
||||
id | integer | | |
|
||||
|
||||
DROP SCHEMA regress_schema_1 CASCADE;
|
||||
NOTICE: drop cascades to table regress_schema_1.tab
|
||||
RESET ROLE;
|
||||
-- Clean up
|
||||
DROP ROLE regress_create_schema_role;
|
@@ -51,7 +51,7 @@ test: copy copyselect copydml insert insert_conflict
|
||||
# ----------
|
||||
# More groups of parallel tests
|
||||
# ----------
|
||||
test: create_misc create_operator create_procedure
|
||||
test: create_misc create_operator create_procedure create_schema
|
||||
# These depend on create_misc and create_operator
|
||||
test: create_index create_index_spgist create_view index_including index_including_gist
|
||||
|
||||
|
70
src/test/regress/sql/create_schema.sql
Normal file
70
src/test/regress/sql/create_schema.sql
Normal file
@@ -0,0 +1,70 @@
|
||||
--
|
||||
-- CREATE_SCHEMA
|
||||
--
|
||||
|
||||
-- Schema creation with elements.
|
||||
|
||||
CREATE ROLE regress_create_schema_role SUPERUSER;
|
||||
|
||||
-- Cases where schema creation fails as objects are qualified with a schema
|
||||
-- that does not match with what's expected.
|
||||
-- This checks all the object types that include schema qualifications.
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE SEQUENCE schema_not_existing.seq;
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE TABLE schema_not_existing.tab (id int);
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE VIEW schema_not_existing.view AS SELECT 1;
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE INDEX ON schema_not_existing.tab (id);
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
|
||||
EXECUTE FUNCTION schema_trig.no_func();
|
||||
-- Again, with a role specification and no schema names.
|
||||
SET ROLE regress_create_schema_role;
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE SEQUENCE schema_not_existing.seq;
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TABLE schema_not_existing.tab (id int);
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE VIEW schema_not_existing.view AS SELECT 1;
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE INDEX ON schema_not_existing.tab (id);
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
|
||||
EXECUTE FUNCTION schema_trig.no_func();
|
||||
-- Again, with a schema name and a role specification.
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE SEQUENCE schema_not_existing.seq;
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TABLE schema_not_existing.tab (id int);
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE VIEW schema_not_existing.view AS SELECT 1;
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE INDEX ON schema_not_existing.tab (id);
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TRIGGER schema_trig BEFORE INSERT ON schema_not_existing.tab
|
||||
EXECUTE FUNCTION schema_trig.no_func();
|
||||
RESET ROLE;
|
||||
|
||||
-- Cases where the schema creation succeeds.
|
||||
-- The schema created matches the role name.
|
||||
CREATE SCHEMA AUTHORIZATION regress_create_schema_role
|
||||
CREATE TABLE regress_create_schema_role.tab (id int);
|
||||
\d regress_create_schema_role.tab
|
||||
DROP SCHEMA regress_create_schema_role CASCADE;
|
||||
-- Again, with a different role specification and no schema names.
|
||||
SET ROLE regress_create_schema_role;
|
||||
CREATE SCHEMA AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TABLE regress_create_schema_role.tab (id int);
|
||||
\d regress_create_schema_role.tab
|
||||
DROP SCHEMA regress_create_schema_role CASCADE;
|
||||
-- Again, with a schema name and a role specification.
|
||||
CREATE SCHEMA regress_schema_1 AUTHORIZATION CURRENT_ROLE
|
||||
CREATE TABLE regress_schema_1.tab (id int);
|
||||
\d regress_schema_1.tab
|
||||
DROP SCHEMA regress_schema_1 CASCADE;
|
||||
RESET ROLE;
|
||||
|
||||
-- Clean up
|
||||
DROP ROLE regress_create_schema_role;
|
Reference in New Issue
Block a user