summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/sp-memory-leak.result21
-rw-r--r--mysql-test/main/sp-memory-leak.test29
-rw-r--r--sql/sql_parse.cc11
-rw-r--r--sql/sql_yacc.yy21
4 files changed, 74 insertions, 8 deletions
diff --git a/mysql-test/main/sp-memory-leak.result b/mysql-test/main/sp-memory-leak.result
new file mode 100644
index 00000000000..aea278801d8
--- /dev/null
+++ b/mysql-test/main/sp-memory-leak.result
@@ -0,0 +1,21 @@
+#
+# MDEV-30680 Warning: Memory not freed: 280 on mangled query, LeakSanitizer: detected memory leaks
+#
+BEGIN NOT ATOMIC
+IF SCALAR() expected_THEN_here;
+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_THEN_here;
+END' at line 2
+BEGIN NOT ATOMIC
+WHILE SCALAR() expected_DO_here;
+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_DO_here;
+END' at line 2
+BEGIN NOT ATOMIC
+REPEAT SELECT 1; UNTIL SCALAR() expected_END_here;
+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
diff --git a/mysql-test/main/sp-memory-leak.test b/mysql-test/main/sp-memory-leak.test
new file mode 100644
index 00000000000..5b346aa8b10
--- /dev/null
+++ b/mysql-test/main/sp-memory-leak.test
@@ -0,0 +1,29 @@
+--echo #
+--echo # MDEV-30680 Warning: Memory not freed: 280 on mangled query, LeakSanitizer: detected memory leaks
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ IF SCALAR() expected_THEN_here;
+END
+$$
+DELIMITER ;$$
+
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ WHILE SCALAR() expected_DO_here;
+END
+$$
+DELIMITER ;$$
+
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ REPEAT SELECT 1; UNTIL SCALAR() expected_END_here;
+END
+$$
+DELIMITER ;$$
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 4c7313265e8..623de4479ae 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -10496,6 +10496,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();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a5a39228776..34120eb3e32 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -98,7 +98,6 @@ int yylex(void *yylval, void *yythd);
#define MYSQL_YYABORT \
do \
{ \
- LEX::cleanup_lex_after_parse_error(thd); \
YYABORT; \
} while (0)
@@ -149,13 +148,6 @@ static Item* escape(THD *thd)
static void yyerror(THD *thd, const char *s)
{
- /*
- 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);
-
/* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
s= ER_THD(thd, ER_SYNTAX_ERROR);
@@ -1521,6 +1513,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <expr_lex>
expr_lex
+%destructor
+{
+ /*
+ In case of a syntax/oom error let's free the sp_expr_lex
+ instance, but only if it has not been linked to any structures
+ such as sp_instr_jump_if_not::m_lex_keeper yet, e.g.:
+ IF f1() THEN1
+ i.e. THEN1 came instead of the expected THEN causing a syntax error.
+ */
+ if (!$$->sp_lex_in_use)
+ delete $$;
+} <expr_lex>
+
%type <assignment_lex>
assignment_source_lex
assignment_source_expr