summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2021-04-23 16:00:29 +0300
committerSergei Petrunia <psergey@askmonty.org>2021-04-23 19:02:38 +0300
commit55491d94a6c0d61f9db9ef5bb7950e2417411633 (patch)
tree85b6b315120dd9946106541a280b8b9d9b5dc5a1
parent75c01f39b1b4a6d27d36d075f8baab9bdda7cc7e (diff)
downloadmariadb-git-bb-10.3-mdev21603.tar.gz
MDEV-21603: Long WHERE IN mariadb 10.3.22 crashbb-10.3-mdev21603
I_S tables and SHOW COMMANDS use special logic for creating and populating temp.tables, e.g. table creation is delayed. The code attempted to apply the same logic for the IN-to-SELECT temptable, which resulted in an attempt to read from not-yet-created temptable and crash. Fix this by restricting use of I_S table logic only to I_S tables.
-rw-r--r--mysql-test/main/information_schema2.result12
-rw-r--r--mysql-test/main/information_schema2.test13
-rw-r--r--sql/sql_base.cc1
-rw-r--r--sql/sql_class.h12
-rw-r--r--sql/sql_derived.cc8
-rw-r--r--sql/sql_prepare.cc2
6 files changed, 41 insertions, 7 deletions
diff --git a/mysql-test/main/information_schema2.result b/mysql-test/main/information_schema2.result
index e23e81b885c..0f24ca3f264 100644
--- a/mysql-test/main/information_schema2.result
+++ b/mysql-test/main/information_schema2.result
@@ -18,3 +18,15 @@ t2
t3
t4
drop table t1, t2, t3, t4;
+#
+# MDEV-21603: Long WHERE IN mariadb 10.3.22 crash
+#
+connect con1,localhost,root,,;
+set @@in_predicate_conversion_threshold=10;
+use mysql;
+show tables where tables_in_mysql in ('1','2','3','4','5','6','7','8','9','boom');
+Tables_in_mysql
+show fields from user where Field in ('1','2','3','4','5','6','7','8','9','boom');
+Field Type Null Key Default Extra
+disconnect con1;
+connection default;
diff --git a/mysql-test/main/information_schema2.test b/mysql-test/main/information_schema2.test
index d2fa3da2b5f..d0cfeefa31a 100644
--- a/mysql-test/main/information_schema2.test
+++ b/mysql-test/main/information_schema2.test
@@ -17,3 +17,16 @@ create table t4 AS select table_name from information_schema.TABLES where table_
delete from t4 where table_name not in (select table_name from information_schema.TABLES where table_schema = database() and table_type = 'BASE TABLE');
select * from t4 order by table_name;
drop table t1, t2, t3, t4;
+
+--echo #
+--echo # MDEV-21603: Long WHERE IN mariadb 10.3.22 crash
+--echo #
+connect (con1,localhost,root,,);
+
+set @@in_predicate_conversion_threshold=10;
+use mysql;
+show tables where tables_in_mysql in ('1','2','3','4','5','6','7','8','9','boom');
+show fields from user where Field in ('1','2','3','4','5','6','7','8','9','boom');
+
+disconnect con1;
+connection default;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 0b17032da8f..4e5b32ce1e5 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -5187,7 +5187,6 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
uint counter;
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
DBUG_ENTER("open_normal_and_derived_tables");
- DBUG_ASSERT(!thd->fill_derived_tables());
if (open_tables(thd, &tables, &counter, flags, &prelocking_strategy) ||
mysql_handle_derived(thd->lex, dt_phases))
goto end;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 5ab93de7957..de2dab3cc14 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3636,9 +3636,17 @@ public:
{
return server_status & SERVER_STATUS_IN_TRANS;
}
- inline bool fill_derived_tables()
+ inline bool fill_derived_table(TABLE_LIST *tl)
{
- return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure();
+ /*
+ Do not fill derived table when
+ 1. running a PREPARE command
+ 2. this is a SHOW command and the table is a temp.table representing
+ the I_S table.
+ */
+ return !stmt_arena->is_stmt_prepare() && // (1)
+ !(lex->only_view_structure() && tl? tl->schema_table_reformed:false); // (2)
+
}
inline bool fill_information_schema_tables()
{
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 50b0178c6c9..33cb6a50710 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -85,14 +85,16 @@ mysql_handle_derived(LEX *lex, uint phases)
break;
if (!(phases & phase_flag))
continue;
- if (phase_flag >= DT_CREATE && !thd->fill_derived_tables())
- break;
for (SELECT_LEX *sl= lex->all_selects_list;
sl && !res;
sl= sl->next_select_in_list())
{
TABLE_LIST *cursor= sl->get_table_list();
+
+ if (phase_flag >= DT_CREATE && !thd->fill_derived_table(cursor))
+ break;
+
sl->changed_elements|= TOUCHED_SEL_DERIVED;
/*
DT_MERGE_FOR_INSERT is not needed for views/derived tables inside
@@ -193,7 +195,7 @@ mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases)
if (phase_flag != DT_PREPARE &&
!(allowed_phases & phase_flag))
continue;
- if (phase_flag >= DT_CREATE && !thd->fill_derived_tables())
+ if (phase_flag >= DT_CREATE && !thd->fill_derived_table(derived))
break;
if ((res= (*processors[phase])(lex->thd, lex, derived)))
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 9775e99afdd..357c1334ee2 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1452,7 +1452,7 @@ static int mysql_test_update(Prepared_statement *stmt,
}
/*
- thd->fill_derived_tables() is false here for sure (because it is
+ thd->fill_derived_table(table_list) is false here for sure (because it is
preparation of PS, so we even do not check it).
*/
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))