From ede526167987b1b35da39a37091a27e6c8f8c6d2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Apr 2005 17:31:59 +0200 Subject: [PATCH 1/2] Fixed BUG#8408: Stored procedure crash if function contains SHOW We simply have to disallow any kind of result set being sent back from a function. Can't see any way to make that to work. mysql-test/r/sp-error.result: New test case for BUG#8408. mysql-test/t/sp-error.test: New test case for BUG#8408. sql/item_func.cc: Disable result sets from functions but temporarily turning CLIENT_MULTI_RESULTS off. sql/share/errmsg.txt: Added error message for statements not allowed in functions (detected during parsing). sql/sql_yacc.yy: Don't allow result sets in functions. --- mysql-test/r/sp-error.result | 48 ++++++++++++++++++++++++++++ mysql-test/t/sp-error.test | 61 ++++++++++++++++++++++++++++++++++++ sql/item_func.cc | 10 ++++++ sql/share/errmsg.txt | 2 ++ sql/sql_yacc.yy | 6 ++++ 5 files changed, 127 insertions(+) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 5ee1d46f3c9..a2478343806 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -594,4 +594,52 @@ alter function bug7047; return 0; end| ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine +drop function if exists bug8408| +drop procedure if exists bug8408| +create function bug8408() returns int +begin +select * from t1; +return 0; +end| +ERROR 0A000: Not allowed to return a result set from a function +create function bug8408() returns int +begin +show warnings; +return 0; +end| +ERROR 0A000: Not allowed to return a result set from a function +create function bug8408(a int) returns int +begin +declare b int; +select b; +return b; +end| +ERROR 0A000: Not allowed to return a result set from a function +create function bug8408() returns int +begin +call bug8408(); +return 0; +end| +create procedure bug8408() +select * from t1| +call bug8408()| +val x +select bug8408()| +ERROR 0A000: SELECT in a stored procedure must have INTO +drop procedure bug8408| +drop function bug8408| +create function bug8408() returns int +begin +declare n int default 0; +select count(*) into n from t1; +return n; +end| +insert into t1 value (2, 2.7), (3, 3.14), (7, 7.0)| +select *,bug8408() from t1| +val x bug8408() +2 2.7 3 +3 3.14 3 +7 7 3 +drop function bug8408| +delete from t1| drop table t1| diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index cb4ebf080f4..b2d24167e49 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -831,6 +831,67 @@ begin end| +# +# BUG#8408: Stored procedure crash if function contains SHOW +# BUG#9058: Stored Procedures: Crash if function included SELECT +# +--disable_warnings +drop function if exists bug8408| +drop procedure if exists bug8408| +--enable_warnings + +# Some things are caught when parsing +--error ER_SP_NO_RETSET_IN_FUNC +create function bug8408() returns int +begin + select * from t1; + return 0; +end| +--error ER_SP_NO_RETSET_IN_FUNC +create function bug8408() returns int +begin + show warnings; + return 0; +end| +--error ER_SP_NO_RETSET_IN_FUNC +create function bug8408(a int) returns int +begin + declare b int; + select b; + return b; +end| + +# Some things must be caught at invokation time +create function bug8408() returns int +begin + call bug8408(); + return 0; +end| +create procedure bug8408() + select * from t1| + +call bug8408()| +--error ER_SP_BADSELECT +select bug8408()| + +drop procedure bug8408| +drop function bug8408| + +# But this is ok +create function bug8408() returns int +begin + declare n int default 0; + select count(*) into n from t1; + return n; +end| + +insert into t1 value (2, 2.7), (3, 3.14), (7, 7.0)| +select *,bug8408() from t1| + +drop function bug8408| +delete from t1| + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/item_func.cc b/sql/item_func.cc index fb21551e22f..3472c0ab786 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4554,6 +4554,7 @@ Item_func_sp::execute(Item **itp) { DBUG_ENTER("Item_func_sp::execute"); THD *thd= current_thd; + bool clcap_mr; int res; #ifndef NO_EMBEDDED_ACCESS_CHECKS st_sp_security_context save_ctx; @@ -4567,6 +4568,9 @@ Item_func_sp::execute(Item **itp) DBUG_RETURN(-1); } + clcap_mr= (thd->client_capabilities & CLIENT_MULTI_RESULTS); + thd->client_capabilities &= ~CLIENT_MULTI_RESULTS; + #ifndef EMBEDDED_LIBRARY my_bool nsok= thd->net.no_send_ok; thd->net.no_send_ok= TRUE; @@ -4582,6 +4586,8 @@ Item_func_sp::execute(Item **itp) m_sp->m_db.str, m_sp->m_name.str, 0)) { sp_restore_security_context(thd, m_sp, &save_ctx); + if (clcap_mr) + thd->client_capabilities |= CLIENT_MULTI_RESULTS; DBUG_RETURN(-1); } #endif @@ -4595,6 +4601,10 @@ Item_func_sp::execute(Item **itp) #ifndef EMBEDDED_LIBRARY thd->net.no_send_ok= nsok; #endif + + if (clcap_mr) + thd->client_capabilities |= CLIENT_MULTI_RESULTS; + DBUG_RETURN(res); } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 8d7a1fe0093..66986a884b3 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5342,3 +5342,5 @@ ER_SP_DUP_HANDLER 42000 eng "Duplicate handler declared in the same block" ER_SP_NOT_VAR_ARG 42000 eng "OUT or INOUT argument %d for routine %s is not a variable" +ER_SP_NO_RETSET_IN_FUNC 0A000 + eng "Not allowed to return a result set from a function" diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 27e75fd9940..80bf409f7a4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1442,6 +1442,12 @@ create_function_tail: LEX *lex= Lex; sp_head *sp= lex->sphead; + if (sp->m_multi_results) + { + my_message(ER_SP_NO_RETSET_IN_FUNC, ER(ER_SP_NO_RETSET_IN_FUNC), + MYF(0)); + YYABORT; + } if (sp->check_backpatch(YYTHD)) YYABORT; lex->sql_command= SQLCOM_CREATE_SPFUNCTION; From 31b3ecaf862cacbfe43731c07e8abf1180165b24 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Apr 2005 18:18:41 +0200 Subject: [PATCH 2/2] Fixed memory leak in Item_func_sp::cleanup(). --- sql/item_func.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/item_func.h b/sql/item_func.h index ba5a6101e4c..1182379ba05 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1301,6 +1301,8 @@ public: void cleanup() { + if (result_field) + delete result_field; Item_func::cleanup(); result_field= NULL; }