diff options
-rw-r--r-- | mysql-test/r/sp-error.result | 11 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 18 | ||||
-rw-r--r-- | sql/sql_parse.cc | 36 |
3 files changed, 58 insertions, 7 deletions
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 43430ca312b..7ee2d168ddd 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -872,3 +872,14 @@ names foo4 drop procedure bug13510_3| drop procedure bug13510_4| +create database mysqltest1; +use mysqltest1; +drop database mysqltest1; +create function f1() returns int return 1; +ERROR 3D000: No database selected +create procedure p1(out param1 int) +begin +select count(*) into param1 from t3; +end| +ERROR 3D000: No database selected +use test; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index b3caa093487..c41be99cb30 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1266,6 +1266,24 @@ drop procedure bug13510_4| delimiter ;| # +# Bug#13514 "server crash when create a stored procedure before choose a +# database" and +# Bug#13587 "Server crash when SP is created without database +# selected" +# +create database mysqltest1; +use mysqltest1; +drop database mysqltest1; +--error ER_NO_DB_ERROR +create function f1() returns int return 1; +delimiter |; +--error ER_NO_DB_ERROR +create procedure p1(out param1 int) +begin + select count(*) into param1 from t3; +end| +delimiter ;| +use test; # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4d9fddec770..8ad7920a556 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4068,6 +4068,19 @@ end_with_restore_list: DBUG_ASSERT(lex->sphead != 0); + if (!lex->sphead->m_db.str || !lex->sphead->m_db.str[0]) + { + if (! thd->db) + { + my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); + delete lex->sphead; + lex->sphead= 0; + goto error; + } + lex->sphead->m_db.length= strlen(thd->db); + lex->sphead->m_db.str= thd->db; + } + if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, is_schema_db(lex->sphead->m_db.str))) { @@ -4077,13 +4090,10 @@ end_with_restore_list: } if (end_active_trans(thd)) - goto error; - - if (!lex->sphead->m_db.str || !lex->sphead->m_db.str[0]) { - lex->sphead->m_db.length= strlen(thd->db); - lex->sphead->m_db.str= strmake_root(thd->mem_root, thd->db, - lex->sphead->m_db.length); + delete lex->sphead; + lex->sphead= 0; + goto error; } name= lex->sphead->name(&namelen); @@ -4110,11 +4120,23 @@ end_with_restore_list: goto error; } + /* + We need to copy name and db in order to use them for + check_routine_access which is called after lex->sphead has + been deleted. + */ name= thd->strdup(name); - db= thd->strmake(lex->sphead->m_db.str, lex->sphead->m_db.length); + lex->sphead->m_db.str= db= thd->strmake(lex->sphead->m_db.str, + lex->sphead->m_db.length); res= (result= lex->sphead->create(thd)); if (result == SP_OK) { + /* + We must cleanup the unit and the lex here because + sp_grant_privileges calls (indirectly) db_find_routine, + which in turn may call yyparse with THD::lex. + TODO: fix db_find_routine to use a temporary lex. + */ lex->unit.cleanup(); delete lex->sphead; lex->sphead= 0; |