summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2018-05-07 17:42:55 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2018-05-15 10:21:50 +0200
commit0bd2b802546c09361fe7823624e09bde16c976ac (patch)
tree10fe4b8b5e528a19b02b2251a5eecb7bf5067464
parent3b99a274a845edddeb2234108d0978d57f447c3d (diff)
downloadmariadb-git-0bd2b802546c09361fe7823624e09bde16c976ac.tar.gz
MDEV-15347: Valgrind or ASAN errors in mysql_make_view on query from information_schema
Make each lex pointing to statement lex instead of global pointer in THD (no need store and restore the global pointer and put it on SP stack).
-rw-r--r--mysql-test/r/sp.result11
-rw-r--r--mysql-test/t/sp.test15
-rw-r--r--sql/sp_head.cc10
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h15
-rw-r--r--sql/sql_lex.cc5
-rw-r--r--sql/sql_lex.h17
-rw-r--r--sql/sql_parse.cc7
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_trigger.cc6
-rw-r--r--sql/sql_view.cc4
11 files changed, 60 insertions, 34 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index ad5bddda035..bc33c08d9d8 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -8242,4 +8242,15 @@ DROP PROCEDURE proc_13;
DROP PROCEDURE proc_select;
DROP TABLE t1, t2;
SET max_sp_recursion_depth=default;
+#
+# MDEV-15347: Valgrind or ASAN errors in mysql_make_view on query
+# from information_schema
+#
+CREATE VIEW v AS SELECT 1;
+CREATE FUNCTION f() RETURNS INT RETURN 1;
+SELECT * FROM INFORMATION_SCHEMA.TABLES JOIN INFORMATION_SCHEMA.PARAMETERS
+UNION
+SELECT * FROM INFORMATION_SCHEMA.TABLES JOIN INFORMATION_SCHEMA.PARAMETERS;
+DROP FUNCTION f;
+DROP VIEW v;
#End of 10.1 tests
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index eeabb0486ca..467d3b5a7d4 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -9754,4 +9754,19 @@ DROP TABLE t1, t2;
SET max_sp_recursion_depth=default;
+--echo #
+--echo # MDEV-15347: Valgrind or ASAN errors in mysql_make_view on query
+--echo # from information_schema
+--echo #
+
+CREATE VIEW v AS SELECT 1;
+CREATE FUNCTION f() RETURNS INT RETURN 1;
+--disable_result_log
+SELECT * FROM INFORMATION_SCHEMA.TABLES JOIN INFORMATION_SCHEMA.PARAMETERS
+UNION
+SELECT * FROM INFORMATION_SCHEMA.TABLES JOIN INFORMATION_SCHEMA.PARAMETERS;
+--enable_result_log
+DROP FUNCTION f;
+DROP VIEW v;
+
--echo #End of 10.1 tests
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 8bf78d97670..0d24ed04eae 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -840,7 +840,7 @@ sp_head::~sp_head()
thd->lex->sphead= NULL;
lex_end(thd->lex);
delete thd->lex;
- thd->lex= thd->stmt_lex= lex;
+ thd->lex= lex;
}
my_hash_free(&m_sptabs);
@@ -1121,7 +1121,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
backup_arena;
query_id_t old_query_id;
TABLE *old_derived_tables;
- LEX *old_lex, *old_stmt_lex;
+ LEX *old_lex;
Item_change_list old_change_list;
String old_packet;
uint old_server_status;
@@ -1224,7 +1224,6 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
do it in each instruction
*/
old_lex= thd->lex;
- old_stmt_lex= thd->stmt_lex;
/*
We should also save Item tree change list to avoid rollback something
too early in the calling query.
@@ -1372,7 +1371,6 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
DBUG_ASSERT(thd->change_list.is_empty());
old_change_list.move_elements_to(&thd->change_list);
thd->lex= old_lex;
- thd->stmt_lex= old_stmt_lex;
thd->set_query_id(old_query_id);
DBUG_ASSERT(!thd->derived_tables);
thd->derived_tables= old_derived_tables;
@@ -2207,7 +2205,7 @@ sp_head::reset_lex(THD *thd)
if (sublex == 0)
DBUG_RETURN(TRUE);
- thd->lex= thd->stmt_lex= sublex;
+ thd->lex= sublex;
(void)m_lex.push_front(oldlex);
/* Reset most stuff. */
@@ -2953,7 +2951,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
We should not save old value since it is saved/restored in
sp_head::execute() when we are entering/leaving routine.
*/
- thd->lex= thd->stmt_lex= m_lex;
+ thd->lex= m_lex;
thd->set_query_id(next_query_id());
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 2ab1cd3a61a..24140246b96 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -3654,7 +3654,7 @@ void Statement::set_statement(Statement *stmt)
{
id= stmt->id;
mark_used_columns= stmt->mark_used_columns;
- stmt_lex= lex= stmt->lex;
+ lex= stmt->lex;
query_string= stmt->query_string;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 341f2e571d8..ca6155ec93f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1028,21 +1028,6 @@ public:
LEX_STRING name; /* name for named prepared statements */
LEX *lex; // parse tree descriptor
/*
- LEX which represents current statement (conventional, SP or PS)
-
- For example during view parsing THD::lex will point to the views LEX and
- THD::stmt_lex will point to LEX of the statement where the view will be
- included
-
- Currently it is used to have always correct select numbering inside
- statement (LEX::current_select_number) without storing and restoring a
- global counter which was THD::select_number.
-
- TODO: make some unified statement representation (now SP has different)
- to store such data like LEX::current_select_number.
- */
- LEX *stmt_lex;
- /*
Points to the query associated with this statement. It's const, but
we need to declare it char * because all table handlers are written
in C and need to point to it.
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 3fa5ec71aeb..085ad1a4b3b 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -657,10 +657,11 @@ void lex_start(THD *thd)
{
LEX *lex= thd->lex;
DBUG_ENTER("lex_start");
- DBUG_PRINT("info", ("Lex %p stmt_lex: %p", thd->lex, thd->stmt_lex));
+ DBUG_PRINT("info", ("Lex %p", thd->lex));
lex->thd= lex->unit.thd= thd;
-
+
+ lex->stmt_lex= lex; // default, should be rewritten for VIEWs And CTEs
DBUG_ASSERT(!lex->explain);
lex->context_stack.empty();
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 4fcd090e1f5..3b47b1d25c9 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -730,7 +730,7 @@ public:
/*
Point to the LEX in which it was created, used in view subquery detection.
- TODO: make also st_select_lex::parent_stmt_lex (see THD::stmt_lex)
+ TODO: make also st_select_lex::parent_stmt_lex (see LEX::stmt_lex)
and use st_select_lex::parent_lex & st_select_lex::parent_stmt_lex
instead of global (from THD) references where it is possible.
*/
@@ -2435,6 +2435,21 @@ struct LEX: public Query_tables_list
// type information
char *length,*dec;
CHARSET_INFO *charset;
+ /*
+ LEX which represents current statement (conventional, SP or PS)
+
+ For example during view parsing THD::lex will point to the views LEX and
+ lex::stmt_lex will point to LEX of the statement where the view will be
+ included
+
+ Currently it is used to have always correct select numbering inside
+ statement (LEX::current_select_number) without storing and restoring a
+ global counter which was THD::select_number.
+
+ TODO: make some unified statement representation (now SP has different)
+ to store such data like LEX::current_select_number.
+ */
+ LEX *stmt_lex;
LEX_STRING name;
char *help_arg;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f83e51409ab..e082155ce1e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6927,8 +6927,9 @@ void THD::reset_for_next_command(bool do_clear_error)
We also assign thd->stmt_lex in lex_start(), but during bootstrap this
code is executed first.
*/
- thd->stmt_lex= &main_lex; thd->stmt_lex->current_select_number= 1;
- DBUG_PRINT("info", ("Lex %p stmt_lex: %p", thd->lex, thd->stmt_lex));
+ DBUG_ASSERT(lex == &main_lex);
+ main_lex.stmt_lex= &main_lex; main_lex.current_select_number= 1;
+ DBUG_PRINT("info", ("Lex and stmt_lex: %p", &main_lex));
/*
Those two lines below are theoretically unneeded as
THD::cleanup_after_query() should take care of this already.
@@ -7046,7 +7047,7 @@ mysql_new_select(LEX *lex, bool move_down)
if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
DBUG_RETURN(1);
- select_lex->select_number= ++thd->stmt_lex->current_select_number;
+ select_lex->select_number= ++thd->lex->stmt_lex->current_select_number;
select_lex->parent_lex= lex; /* Used in init_query. */
select_lex->init_query();
select_lex->init_select();
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 6e14ddc2afb..d39ed6aa637 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -3635,7 +3635,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
if (! (lex= new (mem_root) st_lex_local))
DBUG_RETURN(TRUE);
- stmt_lex= lex;
+ lex->stmt_lex= lex;
if (set_db(thd->db, thd->db_length))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index e14d19c7369..293a4c17156 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -1374,13 +1374,13 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
List_iterator_fast<LEX_STRING> it_client_cs_name(triggers->client_cs_names);
List_iterator_fast<LEX_STRING> it_connection_cl_name(triggers->connection_cl_names);
List_iterator_fast<LEX_STRING> it_db_cl_name(triggers->db_cl_names);
- LEX *old_lex= thd->lex, *old_stmt_lex= thd->stmt_lex;
+ LEX *old_lex= thd->lex;
LEX lex;
sp_rcontext *save_spcont= thd->spcont;
ulonglong save_sql_mode= thd->variables.sql_mode;
LEX_STRING *on_table_name;
- thd->lex= thd->stmt_lex= &lex;
+ thd->lex= &lex;
save_db.str= thd->db;
save_db.length= thd->db_length;
@@ -1579,7 +1579,6 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
}
thd->reset_db(save_db.str, save_db.length);
thd->lex= old_lex;
- thd->stmt_lex= old_stmt_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
@@ -1592,7 +1591,6 @@ err_with_lex_cleanup:
// QQ: anything else ?
lex_end(&lex);
thd->lex= old_lex;
- thd->stmt_lex= old_stmt_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
thd->reset_db(save_db.str, save_db.length);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 1bdc76a66ea..6d7a8e1cc9d 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1315,6 +1315,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
now Lex placed in statement memory
*/
+
table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
if (!table->view)
{
@@ -1340,8 +1341,9 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
goto end;
lex_start(thd);
+ lex->stmt_lex= old_lex;
view_select= &lex->select_lex;
- view_select->select_number= ++thd->stmt_lex->current_select_number;
+ view_select->select_number= ++thd->lex->stmt_lex->current_select_number;
ulonglong saved_mode= thd->variables.sql_mode;
/* switch off modes which can prevent normal parsing of VIEW