summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp-error.result11
-rw-r--r--mysql-test/t/sp-error.test18
-rw-r--r--sql/sql_parse.cc36
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;