mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-30680 Warning: Memory not freed: 280 on mangled query, LeakSanitizer: detected memory leaks
The parser works as follows: The rule expr_lex returns a pointer to a newly created sp_expr_lex instance which is not linked to any MariaDB structures yet - it is pointed only from a Bison stack variable. The sp_expr_lex instance gets linked to other structures (such as sp_instr_jump_if_not) later, after scanning some following grammar. Problem before the fix: If a parse error happened immediately after expr_lex (before it got linked), the created sp_expr_lex value got lost causing a memory leak. Fix: - Using Bison's "destructor" directive to free the results of expr_lex on parse/oom errors. - Moving the call for LEX::cleanup_lex_after_parse_error() from MYSQL_YYABORT and yyerror inside parse_sql(). This is needed because Bison calls destructors after yyerror(), while it's important to delete the sp_expr_lex instance before LEX::cleanup_lex_after_parse_error(). The latter frees the memory root containing the sp_expr_lex instance. After this change the code block are executed in the following order: - yyerror() -- now only raises the error to DA (no cleanup done any more) - %destructor { delete $$; } <expr_lex> -- destructs the sp_expr_lex instance - LEX::cleanup_lex_after_parse_error() -- frees the memory root containing the sp_expr_lex instance - Removing the "delete sublex" related code from restore_lex(): - restore_lex() is called in most cases on success, when delete is not needed. - There is one place when restore_lex() is called on error: In sp_create_assignment_instr(). But in this case LEX::sp_lex_in_use is true anyway. The patch adds a new DBUG_ASSERT(lex->sp_lex_in_use) to guard this.
This commit is contained in:
@ -10454,6 +10454,17 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
|
||||
((thd->variables.sql_mode & MODE_ORACLE) ?
|
||||
ORAparse(thd) :
|
||||
MYSQLparse(thd)) != 0;
|
||||
|
||||
if (mysql_parse_status)
|
||||
{
|
||||
/*
|
||||
Restore the original LEX if it was replaced when parsing
|
||||
a stored procedure. We must ensure that a parsing error
|
||||
does not leave any side effects in the THD.
|
||||
*/
|
||||
LEX::cleanup_lex_after_parse_error(thd);
|
||||
}
|
||||
|
||||
DBUG_ASSERT(opt_bootstrap || mysql_parse_status ||
|
||||
thd->lex->select_stack_top == 0);
|
||||
thd->lex->current_select= thd->lex->first_select_lex();
|
||||
|
Reference in New Issue
Block a user