diff --git a/mysql-test/suite/sys_vars/r/mdev_32640.result b/mysql-test/suite/sys_vars/r/mdev_32640.result new file mode 100644 index 00000000000..ea93f3a7c4a --- /dev/null +++ b/mysql-test/suite/sys_vars/r/mdev_32640.result @@ -0,0 +1,15 @@ +PREPARE s_1 FROM 'SHOW RELAYLOG EVENTS'; +/* 1 */ SET default_master_connection='MASTER'; +/* 1 */ EXECUTE s_1; +ERROR HY000: There is no master connection 'MASTER' +/* 2 */ SET default_master_connection='MASTER'; +/* 2 */ EXECUTE s_1; +ERROR HY000: There is no master connection 'MASTER' +create procedure p() SHOW RELAYLOG EVENTS; +/* 1 */ SET default_master_connection='MASTER'; +/* 1 */ call p; +ERROR HY000: There is no master connection 'MASTER' +/* 2 */ SET default_master_connection='MASTER'; +/* 2 */ call p; +ERROR HY000: There is no master connection 'MASTER' +drop procedure p; diff --git a/mysql-test/suite/sys_vars/t/mdev_32640.test b/mysql-test/suite/sys_vars/t/mdev_32640.test new file mode 100644 index 00000000000..693bb1e9d16 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/mdev_32640.test @@ -0,0 +1,18 @@ +--source include/not_embedded.inc + +PREPARE s_1 FROM 'SHOW RELAYLOG EVENTS'; +/* 1 */ SET default_master_connection='MASTER'; +--error WARN_NO_MASTER_INFO +/* 1 */ EXECUTE s_1; +/* 2 */ SET default_master_connection='MASTER'; +--error WARN_NO_MASTER_INFO +/* 2 */ EXECUTE s_1; + +create procedure p() SHOW RELAYLOG EVENTS; +/* 1 */ SET default_master_connection='MASTER'; +--error WARN_NO_MASTER_INFO +/* 1 */ call p; +/* 2 */ SET default_master_connection='MASTER'; +--error WARN_NO_MASTER_INFO +/* 2 */ call p; +drop procedure p; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index db99dfe6d21..2eb27c43081 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5993,6 +5993,24 @@ finish: thd->wsrep_PA_safe= true; #endif /* WITH_WSREP */ + /* + Reset the connection_name to contain a null string, if the + pointer points to the same space as that of the system variable + default_master_connection. + + We do this because the system variable may be updated which could + free the pointer and create a new one, causing use-after-free for + re-execution of prepared statements and stored procedures where + the LEX may be reused. + + This allows connection_name to be set again be to the system + variable pointer in the next call of this function (see earlier in + this function), after any possible updates to the system variable. + */ + if (thd->lex->mi.connection_name.str == + thd->variables.default_master_connection.str) + thd->lex->mi.connection_name= null_clex_str; + if (lex->sql_command != SQLCOM_SET_OPTION) DEBUG_SYNC(thd, "end_of_statement"); DBUG_RETURN(res || thd->is_error());