summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2005-12-07 00:57:15 +0300
committerunknown <konstantin@mysql.com>2005-12-07 00:57:15 +0300
commit8c2d8ac7503e75d775a3ba78f9c6c4dbbac94266 (patch)
tree8b27e95ca2d3ce79ee1dea5d6db8dc8ac9c515ea
parent3d1e9eae43a2cd353278b18da37c0ab28d88357d (diff)
downloadmariadb-git-8c2d8ac7503e75d775a3ba78f9c6c4dbbac94266.tar.gz
A fix and a test case for Bug#15392 "Server crashes during
prepared statement execute mysql-test/r/sp.result: Test results fixed: a fix for Bug#15392 mysql-test/t/sp.test: A test case for Bug#15392 "Server crashes during prepared statement execute". No test case for error in Item_func_set_user_var::update as the only possible one is OOM. sql/sp_head.cc: A fix for Bug#15392 "Server crashes during prepared statement execute": the bug was caused by mysql_change_db() call which was overwriting the error state of 'ret'. Later in the code, suv->fix_fields() would discover thd->net.report_error and return it without completing its work. As the return value of fix_fields() was ignored, the server would afterwards crash in suv->update(). The fix makes sure that a possible internal error is raised in reset_lex_and_exec_core and then is handled in sp_head::execute_procedure.
-rw-r--r--mysql-test/r/sp.result39
-rw-r--r--mysql-test/t/sp.test46
-rw-r--r--sql/sp_head.cc21
3 files changed, 96 insertions, 10 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 6f0a8623a4c..c78ae13d8ee 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -4153,4 +4153,43 @@ A local variable in a nested compound statement takes precedence over table colu
a - local variable in a nested compound statement
A local variable in a nested compound statement takes precedence over table column in cursors
a - local variable in a nested compound statement
+drop schema if exists mysqltest1|
+Warnings:
+Note 1008 Can't drop database 'mysqltest1'; database doesn't exist
+drop schema if exists mysqltest2|
+Warnings:
+Note 1008 Can't drop database 'mysqltest2'; database doesn't exist
+drop schema if exists mysqltest3|
+Warnings:
+Note 1008 Can't drop database 'mysqltest3'; database doesn't exist
+create schema mysqltest1|
+create schema mysqltest2|
+create schema mysqltest3|
+use mysqltest3|
+create procedure mysqltest1.p1 (out prequestid varchar(100))
+begin
+call mysqltest2.p2('call mysqltest3.p3(1, 2)');
+end|
+create procedure mysqltest2.p2(in psql text)
+begin
+declare lsql text;
+set @lsql= psql;
+prepare lstatement from @lsql;
+execute lstatement;
+deallocate prepare lstatement;
+end|
+create procedure mysqltest3.p3(in p1 int)
+begin
+select p1;
+end|
+call mysqltest1.p1(@rs)|
+ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
+call mysqltest1.p1(@rs)|
+ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
+call mysqltest1.p1(@rs)|
+ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
+drop schema if exists mysqltest1|
+drop schema if exists mysqltest2|
+drop schema if exists mysqltest3|
+use test|
drop table t1,t2;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 81f7609a468..b3760a1d7f5 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -4948,6 +4948,52 @@ end|
call p1("a - stored procedure parameter")|
#
+# A test case for Bug#15392 "Server crashes during prepared statement
+# execute": make sure that stored procedure check for error conditions
+# properly and do not continue execution if an error has been set.
+#
+# It's necessary to use several DBs because in the original code
+# the successful return of mysql_change_db overrode the error from
+# execution.
+drop schema if exists mysqltest1|
+drop schema if exists mysqltest2|
+drop schema if exists mysqltest3|
+create schema mysqltest1|
+create schema mysqltest2|
+create schema mysqltest3|
+use mysqltest3|
+
+create procedure mysqltest1.p1 (out prequestid varchar(100))
+begin
+ call mysqltest2.p2('call mysqltest3.p3(1, 2)');
+end|
+
+create procedure mysqltest2.p2(in psql text)
+begin
+ declare lsql text;
+ set @lsql= psql;
+ prepare lstatement from @lsql;
+ execute lstatement;
+ deallocate prepare lstatement;
+end|
+
+create procedure mysqltest3.p3(in p1 int)
+begin
+ select p1;
+end|
+
+--error ER_SP_WRONG_NO_OF_ARGS
+call mysqltest1.p1(@rs)|
+--error ER_SP_WRONG_NO_OF_ARGS
+call mysqltest1.p1(@rs)|
+--error ER_SP_WRONG_NO_OF_ARGS
+call mysqltest1.p1(@rs)|
+drop schema if exists mysqltest1|
+drop schema if exists mysqltest2|
+drop schema if exists mysqltest3|
+use test|
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index ff4f898924c..fcd220353fc 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1137,10 +1137,12 @@ int sp_head::execute(THD *thd)
original thd->db will then have been freed */
if (dbchanged)
{
- /* No access check when changing back to where we came from.
- (It would generate an error from mysql_change_db() when olddb=="") */
+ /*
+ No access check when changing back to where we came from.
+ (It would generate an error from mysql_change_db() when olddb=="")
+ */
if (! thd->killed)
- ret= mysql_change_db(thd, olddb, 1);
+ ret|= (int) mysql_change_db(thd, olddb, 1);
}
m_flags&= ~IS_INVOKED;
DBUG_PRINT("info", ("first free for 0x%lx --: 0x%lx->0x%lx, level: %lu, flags %x",
@@ -1519,13 +1521,12 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
suv= new Item_func_set_user_var(guv->get_name(), item);
/*
- we do not check suv->fixed, because it can't be fixed after
- creation
+ Item_func_set_user_var is not fixed after construction,
+ call fix_fields().
*/
- suv->fix_fields(thd, &item);
- suv->fix_length_and_dec();
- suv->check();
- suv->update();
+ if ((ret= test(!suv || suv->fix_fields(thd, &item) ||
+ suv->check() || suv->update())))
+ break;
}
}
}
@@ -2097,7 +2098,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
cleanup_items() is called in sp_head::execute()
*/
- return res;
+ return res || thd->net.report_error;
}