summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <pem@mysql.comhem.se>2004-07-22 16:46:59 +0200
committerunknown <pem@mysql.comhem.se>2004-07-22 16:46:59 +0200
commit8a33c2bc8fb816c93baddaa04835d8dc5d7fde35 (patch)
tree14876a18ecd432d2e178feeee4353ad265abbd7d
parentd3558dc3fd5039f0f8981825083a8f7e41c99562 (diff)
downloadmariadb-git-8a33c2bc8fb816c93baddaa04835d8dc5d7fde35.tar.gz
Fixed BUG#4579: Execution of SP crashes server.
Sub-CALLs of procedures zapped thd->current_arena for good. mysql-test/r/sp.result: New test case for BUG#4579. mysql-test/t/sp.test: New test case for BUG#4579. sql/sp_head.cc: Keep and restore old thd->current_arena before/after executing an SP, instead of just setting it to 0 afterwards.
-rw-r--r--mysql-test/r/sp.result21
-rw-r--r--mysql-test/t/sp.test30
-rw-r--r--sql/sp_head.cc16
3 files changed, 61 insertions, 6 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index bbad39c8ad4..eb2d19be56f 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -1387,6 +1387,27 @@ group_concat(v)
yz,yz
drop procedure bug3368|
drop table t3|
+drop table if exists t3|
+create table t3 (f1 int, f2 int);
+insert into t3 values (1,1);
+create procedure bug4579_1 ()
+begin
+declare sf1 int;
+select f1 into sf1 from t3 where f1=1 and f2=1;
+update t3 set f2 = f2 + 1 where f1=1 and f2=1;
+call bug4579_2();
+end|
+create procedure bug4579_2 ()
+begin
+end|
+call bug4579_1()|
+call bug4579_1()|
+Warnings:
+call bug4579_1()|
+Warnings:
+drop procedure bug4579_1|
+drop procedure bug4579_2|
+drop table t3|
drop table if exists fac|
create table fac (n int unsigned not null primary key, f bigint unsigned)|
create procedure ifac(n int unsigned)
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index fbe9060bfa1..4364f4415b3 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -1592,6 +1592,36 @@ call bug3368('yz')|
drop procedure bug3368|
drop table t3|
+#
+# BUG#4579
+#
+--disable_warnings
+drop table if exists t3|
+--enable_warnings
+create table t3 (f1 int, f2 int);
+insert into t3 values (1,1);
+
+create procedure bug4579_1 ()
+begin
+ declare sf1 int;
+
+ select f1 into sf1 from t3 where f1=1 and f2=1;
+ update t3 set f2 = f2 + 1 where f1=1 and f2=1;
+ call bug4579_2();
+end|
+
+create procedure bug4579_2 ()
+begin
+end|
+
+call bug4579_1()|
+call bug4579_1()|
+call bug4579_1()|
+
+drop procedure bug4579_1|
+drop procedure bug4579_2|
+drop table t3|
+
#
# Some "real" examples
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index e32aa391b1d..32c25c98425 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -377,9 +377,11 @@ sp_head::execute(THD *thd)
DBUG_ENTER("sp_head::execute");
char olddb[128];
bool dbchanged;
- sp_rcontext *ctx= thd->spcont;
+ sp_rcontext *ctx;
int ret= 0;
uint ip= 0;
+ Item_arena *old_arena;
+
#ifndef EMBEDDED_LIBRARY
if (check_stack_overrun(thd, olddb))
@@ -392,10 +394,12 @@ sp_head::execute(THD *thd)
if ((ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged)))
goto done;
- if (ctx)
+ if ((ctx= thd->spcont))
ctx->clear_handler();
thd->query_error= 0;
+ old_arena= thd->current_arena;
thd->current_arena= this;
+
do
{
sp_instr *i;
@@ -433,14 +437,14 @@ sp_head::execute(THD *thd)
} while (ret == 0 && !thd->killed && !thd->query_error &&
!thd->net.report_error);
+ if (thd->current_arena)
+ cleanup_items(thd->current_arena->free_list);
+ thd->current_arena= old_arena;
+
done:
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
ret, thd->killed, thd->query_error));
- if (thd->current_arena)
- cleanup_items(thd->current_arena->free_list);
- thd->current_arena= 0;
-
if (thd->killed || thd->query_error || thd->net.report_error)
ret= -1;
/* If the DB has changed, the pointer has changed too, but the