From fdab2c4c648cd3f2db524ef7534843a9d29c4f4f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 29 Jun 2023 17:30:02 +0400 Subject: [PATCH] MDEV-31578 DECLARE CURSOR: "Memory not freed: 280 bytes lost" on syntax error When CURSOR parameters get parsed, their sp_assignment_lex instances (one instance per parameter) get collected to List. These instances get linked to sphead only in the end of the list. If a syntax error happened in the middle of the parameter list, these instances were not deleted, which caused memory leaks. Fix: using a Bison %destructor to free rules of the type (on syntax errors). Afte the fix these sp_assignment_lex instances from CURSOR parameters deleted as follows: - If the CURSOR statement was fully parsed, then these instances get properly linked to sp_head structures, so they are deleted during ~sp_head (this did not change) - If the CURSOR statement failed on a syntax error, then by Bison's %destructor (this is being added in the current patch). --- mysql-test/main/sp-memory-leak.result | 21 +++++++++++++++++++++ mysql-test/main/sp-memory-leak.test | 25 +++++++++++++++++++++++++ sql/sql_lex.h | 6 +++++- sql/sql_yacc.yy | 15 +++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/sp-memory-leak.result b/mysql-test/main/sp-memory-leak.result index aea278801d8..37a0f119341 100644 --- a/mysql-test/main/sp-memory-leak.result +++ b/mysql-test/main/sp-memory-leak.result @@ -19,3 +19,24 @@ END $$ ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'expected_END_here; END' at line 2 +# +# MDEV-31578 DECLARE CURSOR: "Memory not freed: 280 bytes lost" on syntax error +# +BEGIN NOT ATOMIC +DECLARE cur CURSOR (a INT) FOR SELECT a+1; +OPEN cur(sp_followed_by_syntax_error(); +CLOSE cur; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '; +CLOSE cur; +END' at line 3 +BEGIN NOT ATOMIC +DECLARE cur CURSOR (a INT) FOR SELECT a+1; +OPEN cur(1,sp_followed_by_syntax_error(); +CLOSE cur; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '; +CLOSE cur; +END' at line 3 diff --git a/mysql-test/main/sp-memory-leak.test b/mysql-test/main/sp-memory-leak.test index 5b346aa8b10..0035044209a 100644 --- a/mysql-test/main/sp-memory-leak.test +++ b/mysql-test/main/sp-memory-leak.test @@ -27,3 +27,28 @@ BEGIN NOT ATOMIC END $$ DELIMITER ;$$ + + +--echo # +--echo # MDEV-31578 DECLARE CURSOR: "Memory not freed: 280 bytes lost" on syntax error +--echo # + +DELIMITER $$; +--error ER_PARSE_ERROR +BEGIN NOT ATOMIC + DECLARE cur CURSOR (a INT) FOR SELECT a+1; + OPEN cur(sp_followed_by_syntax_error(); + CLOSE cur; +END; +$$ +DELIMITER ;$$ + +DELIMITER $$; +--error ER_PARSE_ERROR +BEGIN NOT ATOMIC + DECLARE cur CURSOR (a INT) FOR SELECT a+1; + OPEN cur(1,sp_followed_by_syntax_error(); + CLOSE cur; +END; +$$ +DELIMITER ;$$ diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 2e3ce7d7503..5538fdd04e6 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3429,7 +3429,11 @@ public: sp_head *sphead; sp_name *spname; bool sp_lex_in_use; // Keep track on lex usage in SPs for error handling - + void delete_if_not_sp_lex_in_use() + { + if (!sp_lex_in_use) + delete this; + } sp_pcontext *spcont; st_sp_chistics sp_chistics; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 601ff119fc3..524da7be4c3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1535,6 +1535,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); cursor_actual_parameters opt_parenthesized_cursor_actual_parameters +%destructor +{ + if ($$) + { + sp_assignment_lex *elem; + List_iterator li(*$$); + while ((elem= li++)) + { + if (!elem->sp_lex_in_use) + delete elem; + } + } +} + + %type option_type opt_var_type opt_var_ident_type