summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-05-30 17:03:26 +0400
committerAlexander Barkov <bar@mariadb.com>2019-05-30 17:03:26 +0400
commitcd1d161c261dcb6f9158bf0a537cb9deee051010 (patch)
treebb4afa8e4b8f143c8aa11ec325eabf91e041ccc7
parentf98bb23168ee9bc0da8aa7111f35cf2539986387 (diff)
downloadmariadb-git-cd1d161c261dcb6f9158bf0a537cb9deee051010.tar.gz
MDEV-19637 Crash on an SP variable assignment to a wrong subselect
-rw-r--r--mysql-test/main/sp.result15
-rw-r--r--mysql-test/main/sp.test23
-rw-r--r--mysql-test/suite/compat/oracle/r/sp.result16
-rw-r--r--mysql-test/suite/compat/oracle/t/sp.test25
-rw-r--r--sql/sql_yacc.yy18
5 files changed, 96 insertions, 1 deletions
diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result
index 3129a2e165c..5908ee24ad4 100644
--- a/mysql-test/main/sp.result
+++ b/mysql-test/main/sp.result
@@ -8792,3 +8792,18 @@ drop procedure p4;
drop table t1;
set @@sql_mode=@save_sql_mode;
# End of 10.3 tests
+#
+# Start of 10.4 tests
+#
+#
+# MDEV-19637 Crash on an SP variable assignment to a wrong subselect
+#
+BEGIN NOT ATOMIC
+DECLARE a INT;
+SET a=(SELECT 1 FROM DUAL UNION SELECT HIGH_PRIORITY 2 FROM DUAL);
+END;
+$$
+ERROR 42000: Incorrect usage/placement of 'HIGH_PRIORITY'
+#
+# End of 10.4 tests
+#
diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test
index 7f841ccd0b4..920b09077d3 100644
--- a/mysql-test/main/sp.test
+++ b/mysql-test/main/sp.test
@@ -10323,3 +10323,26 @@ drop table t1;
set @@sql_mode=@save_sql_mode;
--echo # End of 10.3 tests
+
+
+--echo #
+--echo # Start of 10.4 tests
+--echo #
+
+--echo #
+--echo # MDEV-19637 Crash on an SP variable assignment to a wrong subselect
+--echo #
+
+DELIMITER $$;
+--error ER_CANT_USE_OPTION_HERE
+BEGIN NOT ATOMIC
+ DECLARE a INT;
+ SET a=(SELECT 1 FROM DUAL UNION SELECT HIGH_PRIORITY 2 FROM DUAL);
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # End of 10.4 tests
+--echo #
diff --git a/mysql-test/suite/compat/oracle/r/sp.result b/mysql-test/suite/compat/oracle/r/sp.result
index 6db999b238f..1d088a98ab7 100644
--- a/mysql-test/suite/compat/oracle/r/sp.result
+++ b/mysql-test/suite/compat/oracle/r/sp.result
@@ -2552,3 +2552,19 @@ idx
idx
1
DROP PROCEDURE p1;
+#
+# Start of 10.4 tests
+#
+#
+# MDEV-19637 Crash on an SP variable assignment to a wrong subselect
+#
+DECLARE
+a INT;
+BEGIN
+SET a=(SELECT 1 FROM DUAL UNION SELECT HIGH_PRIORITY 2 FROM DUAL);
+END;
+$$
+ERROR 42000: Incorrect usage/placement of 'HIGH_PRIORITY'
+#
+# End of 10.4 tests
+#
diff --git a/mysql-test/suite/compat/oracle/t/sp.test b/mysql-test/suite/compat/oracle/t/sp.test
index 96b4cd59fbd..4d046533457 100644
--- a/mysql-test/suite/compat/oracle/t/sp.test
+++ b/mysql-test/suite/compat/oracle/t/sp.test
@@ -2387,3 +2387,28 @@ $$
DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Start of 10.4 tests
+--echo #
+
+
+--echo #
+--echo # MDEV-19637 Crash on an SP variable assignment to a wrong subselect
+--echo #
+
+DELIMITER $$;
+--error ER_CANT_USE_OPTION_HERE
+DECLARE
+ a INT;
+BEGIN
+ SET a=(SELECT 1 FROM DUAL UNION SELECT HIGH_PRIORITY 2 FROM DUAL);
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # End of 10.4 tests
+--echo #
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6547bee15ac..3b6e83dd7cc 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -575,8 +575,24 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
return true;
}
lex->pop_select();
- if (Lex->check_main_unit_semantics())
+ if (lex->check_main_unit_semantics())
+ {
+ /*
+ "lex" can be referrenced by:
+ - sp_instr_set SET a= expr;
+ - sp_instr_set_row_field SET r.a= expr;
+ - sp_instr_stmt (just generated above) SET @a= expr;
+ In this case, "lex" is fully owned by sp_instr_xxx and it will
+ be deleted by the destructor ~sp_instr_xxx().
+ So we should remove "lex" from the stack sp_head::m_lex,
+ to avoid double free.
+ Note, in case "lex" is not owned by any sp_instr_xxx,
+ it's also safe to remove it from the stack right now.
+ So we can remove it unconditionally, without testing lex->sp_lex_in_use.
+ */
+ lex->sphead->restore_lex(thd);
return true;
+ }
enum_var_type inner_option_type= lex->option_type;
if (lex->sphead->restore_lex(thd))
return true;