diff options
author | unknown <pem@mysql.comhem.se> | 2004-07-22 16:46:59 +0200 |
---|---|---|
committer | unknown <pem@mysql.comhem.se> | 2004-07-22 16:46:59 +0200 |
commit | 8a33c2bc8fb816c93baddaa04835d8dc5d7fde35 (patch) | |
tree | 14876a18ecd432d2e178feeee4353ad265abbd7d | |
parent | d3558dc3fd5039f0f8981825083a8f7e41c99562 (diff) | |
download | mariadb-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.result | 21 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 30 | ||||
-rw-r--r-- | sql/sp_head.cc | 16 |
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 |