From 877311779d8304bafc3aa24eee2e8af573d7f69f Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 23 Dec 2009 17:44:03 +0400 Subject: [PATCH] Bug#47649 crash during CALL procedure If first call of the procedure is failed on the open_table stage stmt_arena->state is set to EXECUTED state. On second call(if no errors on open_table stage) it leads to use of worng memory arena in find_field_in_view() function as thd->stmt_arena->is_stmt_prepare_or_first_sp_execute() returns FALSE for EXECUTED state. The item is created not in its own arena and it leads to crash on further calls of the procedure. The fix: change state of arena only if no errors on open_table stage happens. mysql-test/r/sp.result: test result mysql-test/t/sp.test: test case sql/sp_head.cc: If first call of the procedure is failed on the open_table stage stmt_arena->state is set to EXECUTED state. On second call(if no errors on open_table stage) it leads to use of worng memory arena in find_field_in_view() function as thd->stmt_arena->is_stmt_prepare_or_first_sp_execute() returns FALSE for EXECUTED state. The item is created not in its own arena and it leads to crash on further calls of the procedure. The fix: change state of arena only if no errors on open_table stage happens. --- mysql-test/r/sp.result | 16 ++++++++++++++++ mysql-test/t/sp.test | 19 +++++++++++++++++++ sql/sp_head.cc | 11 +++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 83ad7545685..1e6227e7380 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6963,6 +6963,22 @@ CALL p1(); CALL p1(); DROP PROCEDURE p1; DROP TABLE t1; +CREATE TABLE t1 ( f1 integer, primary key (f1)); +CREATE TABLE t2 LIKE t1; +CREATE TEMPORARY TABLE t3 LIKE t1; +CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ; +END| +CALL p1; +ERROR HY000: Can't reopen table: 'A' +CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 ); +DROP TABLE t3; +CALL p1; +f1 +CALL p1; +f1 +DROP PROCEDURE p1; +DROP TABLE t1, t2; +DROP VIEW t3; # # Bug #46629: Item_in_subselect::val_int(): Assertion `0' # on subquery inside a SP diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 73ba62612b8..5cf050146dd 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -8242,6 +8242,25 @@ while ($tab_count) DROP PROCEDURE p1; DROP TABLE t1; +# +# Bug#47649 crash during CALL procedure +# +CREATE TABLE t1 ( f1 integer, primary key (f1)); +CREATE TABLE t2 LIKE t1; +CREATE TEMPORARY TABLE t3 LIKE t1; +delimiter |; +CREATE PROCEDURE p1 () BEGIN SELECT f1 FROM t3 AS A WHERE A.f1 IN ( SELECT f1 FROM t3 ) ; +END| +delimiter ;| +--error ER_CANT_REOPEN_TABLE +CALL p1; +CREATE VIEW t3 AS SELECT f1 FROM t2 A WHERE A.f1 IN ( SELECT f1 FROM t2 ); +DROP TABLE t3; +CALL p1; +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1, t2; +DROP VIEW t3; --echo # --echo # Bug #46629: Item_in_subselect::val_int(): Assertion `0' diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 51a731138ca..d74e195048f 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2773,8 +2773,15 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, m_lex->mark_as_requiring_prelocking(NULL); } thd->rollback_item_tree_changes(); - /* Update the state of the active arena. */ - thd->stmt_arena->state= Query_arena::EXECUTED; + /* + Update the state of the active arena if no errors on + open_tables stage. + */ + if (!res || !thd->is_error() || + (thd->main_da.sql_errno() != ER_CANT_REOPEN_TABLE && + thd->main_da.sql_errno() != ER_NO_SUCH_TABLE && + thd->main_da.sql_errno() != ER_UPDATE_TABLE_USED)) + thd->stmt_arena->state= Query_arena::EXECUTED; /* Merge here with the saved parent's values