1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Fixed BUG#16887: Cursor causes server segfault

The problem was a code generation bug: cpop instructions were not generated
  when using ITERATE back to an outer block from a context with a declared
  cursor; this would make it push a new cursor without popping in-between,
  eventually overrunning the cursor stack with a crash as the result.
  Fixed the calculation of how many cursors to pop (in sp_pcontext.cc:
  diff_cursors()), and also corrected diff_cursors() and diff_handlers()
  to when doing a "leave"; don't include the last context we're leaving
  (we are then jumping to the appropriate pop instructions).
This commit is contained in:
pem@mysql.com
2006-02-15 12:11:29 +01:00
parent d67b0a6bf6
commit cfba31dd46
5 changed files with 133 additions and 11 deletions

View File

@ -4519,4 +4519,60 @@ Handler
Inner
drop procedure bug15011|
drop table t3|
drop table if exists t3|
drop procedure if exists bug16887|
create table t3 ( c varchar(1) )|
insert into t3 values
(' '),('.'),(';'),(','),('-'),('_'),('('),(')'),('/'),('\\')|
create procedure bug16887()
begin
declare i int default 10;
again:
while i > 0 do
begin
declare breakchar varchar(1);
declare done int default 0;
declare t3_cursor cursor for select c from t3;
declare continue handler for not found set done = 1;
set i = i - 1;
select i;
if i = 3 then
iterate again;
end if;
open t3_cursor;
loop
fetch t3_cursor into breakchar;
if done = 1 then
begin
close t3_cursor;
iterate again;
end;
end if;
end loop;
end;
end while;
end|
call bug16887()|
i
9
i
8
i
7
i
6
i
5
i
4
i
3
i
2
i
1
i
0
drop table t3|
drop procedure bug16887|
drop table t1,t2;

View File

@ -5311,6 +5311,60 @@ drop procedure bug15011|
drop table t3|
#
# BUG#16887: Cursor causes server segfault
#
--disable_warnings
drop table if exists t3|
drop procedure if exists bug16887|
--enable_warnings
create table t3 ( c varchar(1) )|
insert into t3 values
(' '),('.'),(';'),(','),('-'),('_'),('('),(')'),('/'),('\\')|
create procedure bug16887()
begin
declare i int default 10;
again:
while i > 0 do
begin
declare breakchar varchar(1);
declare done int default 0;
declare t3_cursor cursor for select c from t3;
declare continue handler for not found set done = 1;
set i = i - 1;
select i;
if i = 3 then
iterate again;
end if;
open t3_cursor;
loop
fetch t3_cursor into breakchar;
if done = 1 then
begin
close t3_cursor;
iterate again;
end;
end if;
end loop;
end;
end while;
end|
call bug16887()|
drop table t3|
drop procedure bug16887|
#
# BUG#NNNN: New bug synopsis
#

View File

@ -122,30 +122,38 @@ sp_pcontext::pop_context()
}
uint
sp_pcontext::diff_handlers(sp_pcontext *ctx)
sp_pcontext::diff_handlers(sp_pcontext *ctx, bool exclusive)
{
uint n= 0;
sp_pcontext *pctx= this;
sp_pcontext *last_ctx= NULL;
while (pctx && pctx != ctx)
{
n+= pctx->m_handlers;
last_ctx= pctx;
pctx= pctx->parent_context();
}
if (pctx)
return n;
return (exclusive && last_ctx ? n - last_ctx->m_handlers : n);
return 0; // Didn't find ctx
}
uint
sp_pcontext::diff_cursors(sp_pcontext *ctx)
sp_pcontext::diff_cursors(sp_pcontext *ctx, bool exclusive)
{
uint n= 0;
sp_pcontext *pctx= this;
sp_pcontext *last_ctx= NULL;
while (pctx && pctx != ctx)
{
n+= pctx->m_cursor.elements;
last_ctx= pctx;
pctx= pctx->parent_context();
}
if (pctx)
return ctx->current_cursors() - pctx->current_cursors();
return (exclusive && last_ctx ? n - last_ctx->m_cursor.elements : n);
return 0; // Didn't find ctx
}

View File

@ -119,11 +119,15 @@ class sp_pcontext : public Sql_alloc
return m_parent;
}
/*
Number of handlers/cursors to pop between this context and 'ctx'.
If 'exclusive' is true, don't count the last block we are leaving;
this is used for LEAVE where we will jump to the cpop/hpop instructions.
*/
uint
diff_handlers(sp_pcontext *ctx);
diff_handlers(sp_pcontext *ctx, bool exclusive);
uint
diff_cursors(sp_pcontext *ctx);
diff_cursors(sp_pcontext *ctx, bool exclusive);
//

View File

@ -2079,10 +2079,10 @@ sp_proc_stmt:
uint ip= sp->instructions();
uint n;
n= ctx->diff_handlers(lab->ctx);
n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */
if (n)
sp->add_instr(new sp_instr_hpop(ip++, ctx, n));
n= ctx->diff_cursors(lab->ctx);
n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */
if (n)
sp->add_instr(new sp_instr_cpop(ip++, ctx, n));
i= new sp_instr_jump(ip, ctx);
@ -2108,10 +2108,10 @@ sp_proc_stmt:
uint ip= sp->instructions();
uint n;
n= ctx->diff_handlers(lab->ctx);
n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
if (n)
sp->add_instr(new sp_instr_hpop(ip++, ctx, n));
n= ctx->diff_cursors(lab->ctx);
n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
if (n)
sp->add_instr(new sp_instr_cpop(ip++, ctx, n));
i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */