aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_utilcmd.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2023-04-28 19:29:12 +0900
committerMichael Paquier <michael@paquier.xyz>2023-04-28 19:29:12 +0900
commit4dadd660f0719206ce3914d4ad9b6aad69d6db6e (patch)
tree0f28894449b485317679ef670a0a008a61b188d2 /src/backend/parser/parse_utilcmd.c
parent4a6603cd4650a335ee38d894d7bbb452b1bf822f (diff)
downloadpostgresql-4dadd660f0719206ce3914d4ad9b6aad69d6db6e.tar.gz
postgresql-4dadd660f0719206ce3914d4ad9b6aad69d6db6e.zip
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
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r--src/backend/parser/parse_utilcmd.c38
1 files changed, 19 insertions, 19 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index b0f6fe4fa61..b1255e3b709 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -95,12 +95,10 @@ typedef struct
bool ofType; /* true if statement contains OF typename */
} CreateStmtContext;
-/* State shared by transformCreateSchemaStmt and its subroutines */
+/* State shared by transformCreateSchemaStmtElements and its subroutines */
typedef struct
{
- const char *stmtType; /* "CREATE SCHEMA" or "ALTER SCHEMA" */
- char *schemaname; /* name of schema */
- RoleSpec *authrole; /* owner of schema */
+ const char *schemaname; /* name of schema */
List *sequences; /* CREATE SEQUENCE items */
List *tables; /* CREATE TABLE items */
List *views; /* CREATE VIEW items */
@@ -134,7 +132,7 @@ static void transformCheckConstraints(CreateStmtContext *cxt,
static void transformConstraintAttrs(CreateStmtContext *cxt,
List *constraintList);
static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
-static void setSchemaName(char *context_schema, char **stmt_schema_name);
+static void setSchemaName(const char *context_schema, char **stmt_schema_name);
static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd);
static List *transformPartitionRangeBounds(ParseState *pstate, List *blist,
Relation parent);
@@ -3784,14 +3782,18 @@ transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
/*
- * transformCreateSchemaStmt -
- * analyzes the CREATE SCHEMA statement
+ * transformCreateSchemaStmtElements -
+ * analyzes the elements of a CREATE SCHEMA statement
*
- * Split the schema element list into individual commands and place
- * them in the result list in an order such that there are no forward
- * references (e.g. GRANT to a table created later in the list). Note
- * that the logic we use for determining forward references is
- * presently quite incomplete.
+ * Split the schema element list from a CREATE SCHEMA statement into
+ * individual commands and place them in the result list in an order
+ * such that there are no forward references (e.g. GRANT to a table
+ * created later in the list). Note that the logic we use for determining
+ * forward references is presently quite incomplete.
+ *
+ * "schemaName" is the name of the schema that will be used for the creation
+ * of the objects listed, that may be compiled from the schema name defined
+ * in the statement or a role specification.
*
* SQL also allows constraints to make forward references, so thumb through
* the table columns and move forward references to a posterior alter-table
@@ -3807,15 +3809,13 @@ transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
* extent.
*/
List *
-transformCreateSchemaStmt(CreateSchemaStmt *stmt)
+transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
{
CreateSchemaStmtContext cxt;
List *result;
ListCell *elements;
- cxt.stmtType = "CREATE SCHEMA";
- cxt.schemaname = stmt->schemaname;
- cxt.authrole = (RoleSpec *) stmt->authrole;
+ cxt.schemaname = schemaName;
cxt.sequences = NIL;
cxt.tables = NIL;
cxt.views = NIL;
@@ -3827,7 +3827,7 @@ transformCreateSchemaStmt(CreateSchemaStmt *stmt)
* Run through each schema element in the schema element list. Separate
* statements by type, and do preliminary analysis.
*/
- foreach(elements, stmt->schemaElts)
+ foreach(elements, schemaElts)
{
Node *element = lfirst(elements);
@@ -3912,10 +3912,10 @@ transformCreateSchemaStmt(CreateSchemaStmt *stmt)
* Set or check schema name in an element of a CREATE SCHEMA command
*/
static void
-setSchemaName(char *context_schema, char **stmt_schema_name)
+setSchemaName(const char *context_schema, char **stmt_schema_name)
{
if (*stmt_schema_name == NULL)
- *stmt_schema_name = context_schema;
+ *stmt_schema_name = unconstify(char *, context_schema);
else if (strcmp(context_schema, *stmt_schema_name) != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),