diff options
author | unknown <davi@mysql.com/endora.local> | 2008-02-21 14:58:29 -0300 |
---|---|---|
committer | unknown <davi@mysql.com/endora.local> | 2008-02-21 14:58:29 -0300 |
commit | 315665cf67dd4e56922955b051eff2c384f2298e (patch) | |
tree | 09d15a0c10b54a7ad010fa850101c4816d4e0d16 /sql/sql_view.cc | |
parent | fa08b280857fde69a70c68bd07797624a52ef262 (diff) | |
download | mariadb-git-315665cf67dd4e56922955b051eff2c384f2298e.tar.gz |
Bug#32890 Crash after repeated create and drop of tables and views
The problem is that CREATE VIEW statements inside prepared statements
weren't being expanded during the prepare phase, which leads to objects
not being allocated in the appropriate memory arenas.
The solution is to perform the validation of CREATE VIEW statements
during the prepare phase of a prepared statement. The validation
during the prepare phase assures that transformations of the parsed
tree will use the permanent arena of the prepared statement.
mysql-test/r/ps.result:
Add test case result for Bug#32890
mysql-test/t/ps.test:
Add test case for Bug#32890
sql/item.h:
Restore original field name if name is auto generated.
sql/sql_prepare.cc:
Validate and prepare a CREATE VIEW statement for execution.
sql/sql_view.cc:
Move privileges check to it's own function.
sql/sql_view.h:
Export function which check privileges of a CREATE VIEW statement.
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r-- | sql/sql_view.cc | 213 |
1 files changed, 126 insertions, 87 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 48ab5b3af9e..4c8e6e80c41 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -227,104 +227,31 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) return FALSE; } +#ifndef NO_EMBEDDED_ACCESS_CHECKS /** - @brief Creating/altering VIEW procedure + @brief CREATE VIEW privileges pre-check. @param thd thread handler + @param tables tables used in the view @param views views to create @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE - @note This function handles both create and alter view commands. - @retval FALSE Operation was a success. @retval TRUE An error occured. */ -bool mysql_create_view(THD *thd, TABLE_LIST *views, - enum_view_create_mode mode) +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + enum_view_create_mode mode) { LEX *lex= thd->lex; - bool link_to_local; /* first table in list is target VIEW name => cut off it */ - TABLE_LIST *view= lex->unlink_first_table(&link_to_local); - TABLE_LIST *tables= lex->query_tables; TABLE_LIST *tbl; SELECT_LEX *select_lex= &lex->select_lex; -#ifndef NO_EMBEDDED_ACCESS_CHECKS SELECT_LEX *sl; -#endif - SELECT_LEX_UNIT *unit= &lex->unit; - bool res= FALSE; - DBUG_ENTER("mysql_create_view"); - - /* This is ensured in the parser. */ - DBUG_ASSERT(!lex->proc_list.first && !lex->result && - !lex->param_list.elements && !lex->derived_tables); - - if (mode != VIEW_CREATE_NEW) - { - if (mode == VIEW_ALTER && - fill_defined_view_parts(thd, view)) - { - res= TRUE; - goto err; - } - sp_cache_invalidate(); - } + bool res= TRUE; + DBUG_ENTER("create_view_precheck"); - if (!lex->definer) - { - /* - DEFINER-clause is missing; we have to create default definer in - persistent arena to be PS/SP friendly. - If this is an ALTER VIEW then the current user should be set as - the definer. - */ - Query_arena original_arena; - Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); - - if (!(lex->definer= create_default_definer(thd))) - res= TRUE; - - if (ps_arena) - thd->restore_active_arena(ps_arena, &original_arena); - - if (res) - goto err; - } - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* - check definer of view: - - same as current user - - current user has SUPER_ACL - */ - if (lex->definer && - (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || - my_strcasecmp(system_charset_info, - lex->definer->host.str, - thd->security_ctx->priv_host) != 0)) - { - if (!(thd->security_ctx->master_access & SUPER_ACL)) - { - my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - res= TRUE; - goto err; - } - else - { - if (!is_acl_user(lex->definer->host.str, - lex->definer->user.str)) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_NO_SUCH_USER, - ER(ER_NO_SUCH_USER), - lex->definer->user.str, - lex->definer->host.str); - } - } - } /* Privilege check for view creation: - user has CREATE VIEW privilege on view table @@ -346,10 +273,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, 0, 0, is_schema_db(view->db)) || grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0)))) - { - res= TRUE; goto err; - } + for (sl= select_lex; sl; sl= sl->next_select()) { for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) @@ -363,7 +288,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY", thd->security_ctx->priv_user, thd->security_ctx->priv_host, tbl->table_name); - res= TRUE; goto err; } /* @@ -399,10 +323,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, if (check_access(thd, SELECT_ACL, tbl->db, &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) || grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0)) - { - res= TRUE; goto err; - } } } } @@ -426,8 +347,126 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, } } } + + res= FALSE; + +err: + DBUG_RETURN(res || thd->net.report_error); +} + +#else + +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + enum_view_create_mode mode) +{ + return FALSE; +} + +#endif + + +/** + @brief Creating/altering VIEW procedure + + @param thd thread handler + @param views views to create + @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE + + @note This function handles both create and alter view commands. + + @retval FALSE Operation was a success. + @retval TRUE An error occured. +*/ + +bool mysql_create_view(THD *thd, TABLE_LIST *views, + enum_view_create_mode mode) +{ + LEX *lex= thd->lex; + bool link_to_local; + /* first table in list is target VIEW name => cut off it */ + TABLE_LIST *view= lex->unlink_first_table(&link_to_local); + TABLE_LIST *tables= lex->query_tables; + TABLE_LIST *tbl; + SELECT_LEX *select_lex= &lex->select_lex; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + SELECT_LEX *sl; +#endif + SELECT_LEX_UNIT *unit= &lex->unit; + bool res= FALSE; + DBUG_ENTER("mysql_create_view"); + + /* This is ensured in the parser. */ + DBUG_ASSERT(!lex->proc_list.first && !lex->result && + !lex->param_list.elements && !lex->derived_tables); + + if (mode != VIEW_CREATE_NEW) + { + if (mode == VIEW_ALTER && + fill_defined_view_parts(thd, view)) + { + res= TRUE; + goto err; + } + sp_cache_invalidate(); + } + + if (!lex->definer) + { + /* + DEFINER-clause is missing; we have to create default definer in + persistent arena to be PS/SP friendly. + If this is an ALTER VIEW then the current user should be set as + the definer. + */ + Query_arena original_arena; + Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); + + if (!(lex->definer= create_default_definer(thd))) + res= TRUE; + + if (ps_arena) + thd->restore_active_arena(ps_arena, &original_arena); + + if (res) + goto err; + } + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* + check definer of view: + - same as current user + - current user has SUPER_ACL + */ + if (lex->definer && + (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || + my_strcasecmp(system_charset_info, + lex->definer->host.str, + thd->security_ctx->priv_host) != 0)) + { + if (!(thd->security_ctx->master_access & SUPER_ACL)) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + res= TRUE; + goto err; + } + else + { + if (!is_acl_user(lex->definer->host.str, + lex->definer->user.str)) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_NO_SUCH_USER, + ER(ER_NO_SUCH_USER), + lex->definer->user.str, + lex->definer->host.str); + } + } + } #endif + if ((res= create_view_precheck(thd, tables, view, mode))) + goto err; + if (open_and_lock_tables(thd, tables)) { res= TRUE; |