mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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.
This commit is contained in:
@ -1387,6 +1387,27 @@ group_concat(v)
|
|||||||
yz,yz
|
yz,yz
|
||||||
drop procedure bug3368|
|
drop procedure bug3368|
|
||||||
drop table t3|
|
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|
|
drop table if exists fac|
|
||||||
create table fac (n int unsigned not null primary key, f bigint unsigned)|
|
create table fac (n int unsigned not null primary key, f bigint unsigned)|
|
||||||
create procedure ifac(n int unsigned)
|
create procedure ifac(n int unsigned)
|
||||||
|
@ -1592,6 +1592,36 @@ call bug3368('yz')|
|
|||||||
drop procedure bug3368|
|
drop procedure bug3368|
|
||||||
drop table t3|
|
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
|
# Some "real" examples
|
||||||
|
@ -377,9 +377,11 @@ sp_head::execute(THD *thd)
|
|||||||
DBUG_ENTER("sp_head::execute");
|
DBUG_ENTER("sp_head::execute");
|
||||||
char olddb[128];
|
char olddb[128];
|
||||||
bool dbchanged;
|
bool dbchanged;
|
||||||
sp_rcontext *ctx= thd->spcont;
|
sp_rcontext *ctx;
|
||||||
int ret= 0;
|
int ret= 0;
|
||||||
uint ip= 0;
|
uint ip= 0;
|
||||||
|
Item_arena *old_arena;
|
||||||
|
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
if (check_stack_overrun(thd, olddb))
|
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)))
|
if ((ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged)))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (ctx)
|
if ((ctx= thd->spcont))
|
||||||
ctx->clear_handler();
|
ctx->clear_handler();
|
||||||
thd->query_error= 0;
|
thd->query_error= 0;
|
||||||
|
old_arena= thd->current_arena;
|
||||||
thd->current_arena= this;
|
thd->current_arena= this;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
sp_instr *i;
|
sp_instr *i;
|
||||||
@ -433,14 +437,14 @@ sp_head::execute(THD *thd)
|
|||||||
} while (ret == 0 && !thd->killed && !thd->query_error &&
|
} while (ret == 0 && !thd->killed && !thd->query_error &&
|
||||||
!thd->net.report_error);
|
!thd->net.report_error);
|
||||||
|
|
||||||
|
if (thd->current_arena)
|
||||||
|
cleanup_items(thd->current_arena->free_list);
|
||||||
|
thd->current_arena= old_arena;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
|
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
|
||||||
ret, thd->killed, thd->query_error));
|
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)
|
if (thd->killed || thd->query_error || thd->net.report_error)
|
||||||
ret= -1;
|
ret= -1;
|
||||||
/* If the DB has changed, the pointer has changed too, but the
|
/* If the DB has changed, the pointer has changed too, but the
|
||||||
|
Reference in New Issue
Block a user