From 24693c6fcf041f5ee7d5c9d3215094bde6da4bc8 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 27 Apr 2021 16:08:33 +0200 Subject: [PATCH] Bug#29363867: LOST CONNECTION TO MYSQL SERVER DURING QUERY The problem is that sharing default expression among set instruction leads to attempt access result field of function created in other instruction runtime MEM_ROOT and already freed (a bit different then MySQL problem). Fix is the same as in MySQL (but no optimisation for constant), turn DECLARE a, b, c type DEFAULT expr; to DECLARE a type DEFAULT expr, b type DEFAULT a, c type DEFAULT a; --- mysql-test/r/sp.result | 15 +++++++++++ mysql-test/suite/funcs_1/r/storedproc.result | 26 +++++++++--------- mysql-test/t/sp.test | 19 +++++++++++++ sql/sql_yacc.yy | 28 +++++++++++++++++--- 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index b679f3f54fc..25675a11f4a 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -8486,4 +8486,19 @@ ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1; +# +# BUG#30366310: USING A FUNCTION TO ASSIGN DEFAULT VALUES TO +# 2 OR MORE VARIABLES CRASHES SERVER +# +create function f1() returns bigint return now()-1| +create procedure p1() +begin +declare b, c bigint default f1(); +select b-c; +end| +call p1()| +b-c +0 +drop procedure p1| +drop function f1| #End of 10.2 tests diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result index ac48e20eaed..516ea983563 100644 --- a/mysql-test/suite/funcs_1/r/storedproc.result +++ b/mysql-test/suite/funcs_1/r/storedproc.result @@ -7125,7 +7125,7 @@ CALL sp1(); x y z 000 000 000 Warnings: -Warning 1264 Out of range value for column 'z' at row 1 +Warning 1264 Out of range value for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7163,7 +7163,7 @@ CALL sp1(); x y z 00000 00000 00000 Warnings: -Warning 1264 Out of range value for column 'z' at row 1 +Warning 1264 Out of range value for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7201,7 +7201,7 @@ CALL sp1(); x y z 00000000 00000000 00000000 Warnings: -Warning 1264 Out of range value for column 'z' at row 1 +Warning 1264 Out of range value for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7239,7 +7239,7 @@ CALL sp1(); x y z 0000000000 0000000000 0000000000 Warnings: -Warning 1264 Out of range value for column 'z' at row 1 +Warning 1264 Out of range value for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7277,7 +7277,7 @@ CALL sp1(); x y z 00000000000000000000 00000000000000000000 00000000000000000000 Warnings: -Warning 1264 Out of range value for column 'z' at row 1 +Warning 1264 Out of range value for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7297,7 +7297,7 @@ CALL sp1(); x y z -9999999999 -9999999999 -9999999999 Warnings: -Warning 1264 Out of range value for column 'z' at row 1 +Warning 1264 Out of range value for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7308,7 +7308,7 @@ CALL sp1(); x y z 0 0 0 Warnings: -Note 1265 Data truncated for column 'z' at row 1 +Note 1265 Data truncated for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7319,7 +7319,7 @@ CALL sp1(); x y z 0000000000 0000000000 0000000000 Warnings: -Warning 1264 Out of range value for column 'z' at row 1 +Warning 1264 Out of range value for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7330,7 +7330,7 @@ CALL sp1(); x y z 0000000000 0000000000 0000000000 Warnings: -Note 1265 Data truncated for column 'z' at row 1 +Note 1265 Data truncated for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7341,7 +7341,7 @@ CALL sp1(); x y z 0 0 0 Warnings: -Note 1265 Data truncated for column 'z' at row 1 +Note 1265 Data truncated for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7352,7 +7352,7 @@ CALL sp1(); x y z 0 0 0 Warnings: -Note 1265 Data truncated for column 'z' at row 1 +Note 1265 Data truncated for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7363,7 +7363,7 @@ CALL sp1(); x y z 0000000000 0000000000 0000000000 Warnings: -Note 1265 Data truncated for column 'z' at row 1 +Note 1265 Data truncated for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN @@ -7374,7 +7374,7 @@ CALL sp1(); x y z 0000000000 0000000000 0000000000 Warnings: -Note 1265 Data truncated for column 'z' at row 1 +Note 1265 Data truncated for column 'x' at row 1 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( ) BEGIN diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f13b3fbc281..0ef5e7d0b6e 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -10025,4 +10025,23 @@ DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1; + +--echo # +--echo # BUG#30366310: USING A FUNCTION TO ASSIGN DEFAULT VALUES TO +--echo # 2 OR MORE VARIABLES CRASHES SERVER +--echo # + +delimiter |; +create function f1() returns bigint return now()-1| +create procedure p1() +begin + declare b, c bigint default f1(); + select b-c; +end| +call p1()| +drop procedure p1| +drop function f1| +delimiter ;| + + --echo #End of 10.2 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6eb47f1e49f..387c77a4ef5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3104,17 +3104,22 @@ sp_decl: sp_pcontext *pctx= lex->spcont; uint num_vars= pctx->context_var_count(); Item *dflt_value_item= $5; + const bool has_default_clause = (dflt_value_item != NULL); Lex->set_last_field_type($4); - if (!dflt_value_item) + + if (!has_default_clause) { dflt_value_item= new (thd->mem_root) Item_null(thd); if (dflt_value_item == NULL) MYSQL_YYABORT; /* QQ Set to the var_type with null_value? */ } - - for (uint i = num_vars-$2 ; i < num_vars ; i++) + + sp_variable *first_spvar = NULL; + const uint first_var_num = num_vars - $2; + + for (uint i = first_var_num ; i < num_vars ; i++) { uint var_idx= pctx->var_context2runtime(i); sp_variable *spvar= pctx->find_variable(var_idx); @@ -3126,9 +3131,24 @@ sp_decl: if (!last) spvar->field_def= *lex->last_field; + if (i == first_var_num) { + first_spvar = spvar; + } else if (has_default_clause) { + Item_splocal *item = + new (thd->mem_root) + Item_splocal(thd, first_spvar->name, first_spvar->offset, + first_spvar->sql_type(), 0, 0); + if (item == NULL) + MYSQL_YYABORT; // OOM +#ifndef DBUG_OFF + item->m_sp = lex->sphead; +#endif + dflt_value_item = item; + } + spvar->default_value= dflt_value_item; spvar->field_def.field_name= spvar->name.str; - + if (lex->sphead->fill_field_definition(thd, lex, &spvar->field_def)) {