summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRex <rex.johnston@mariadb.com>2023-02-01 15:59:39 +1200
committerRex <rex.johnston@mariadb.com>2023-03-06 08:29:09 +1200
commit99c0e243dee351f3a458ae66bd4a77790f8ff441 (patch)
tree7c6efc5c02986ed326c269d7e9ed6d80a15c3729
parentb05218e08f45a17f46d1b73cbb9dcb2969dc04cd (diff)
downloadmariadb-git-bb-10.4-MDEV-23384.tar.gz
MDEV-23384 Server crashes in subselect_indexsubquery_engine::print with optimizer trace enabledbb-10.4-MDEV-23384
unitialized data structures causing subselect_indexsubquery_engine::print and subselect_uniquesubquery_engine::print to crash when optimizer_trace is enabled
-rw-r--r--mysql-test/main/opt_trace.result47
-rw-r--r--mysql-test/main/opt_trace.test64
-rw-r--r--sql/item_subselect.cc19
3 files changed, 123 insertions, 7 deletions
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 2eef0da62bb..3ab3ab16a43 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -8522,5 +8522,52 @@ SELECT a FROM t1 WHERE (a,b) in (SELECT @c,@d);
a
DROP TABLE t1;
#
+# MDEV-23384: Server crashes in subselect_indexsubquery_engine::print with optimizer trace enabled
+#
+# test subselect_indexsubquery_engine::print
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (3),(4);
+CREATE TABLE t3 (c INT);
+CREATE TABLE t4 (d INT);
+INSERT INTO t4 VALUES (5),(6);
+SET SESSION optimizer_trace= 'enabled=on';
+UPDATE t1, t2 SET t2.b = 1 WHERE
+(
+WITH cte1 AS
+(
+SELECT MAX(c) FROM t3 WHERE c = 0 OR c IN
+(
+WITH cte2 AS
+(
+SELECT d FROM t4
+)
+SELECT * FROM cte2
+)
+)
+SELECT * FROM cte1
+) IS NULL;
+# test subselect_uniquesubquery_engine::print
+CREATE TABLE t10 (a int, b int) ENGINE=myisam;
+CREATE TABLE t11 (a int, b int, unique(a));
+INSERT INTO t11 SELECT seq, seq FROM seq_1_to_10;
+CREATE TABLE t12 (a int, key(a));
+INSERT INTO t12 SELECT seq FROM seq_1_to_1000;
+SET SESSION optimizer_trace= 'enabled=on';
+SELECT * FROM t12 WHERE t12.a <
+(
+SELECT b FROM
+(
+SELECT b FROM t10 WHERE a <3 or a in
+(
+SELECT a FROM t11 WHERE t11.b<t10.b
+)
+LIMIT 2
+) T
+);
+a
+DROP TABLE t1, t2, t3, t4, t10, t11, t12;
+#
# End of 10.4 tests
#
diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test
index 0785d828a07..727af02c35d 100644
--- a/mysql-test/main/opt_trace.test
+++ b/mysql-test/main/opt_trace.test
@@ -678,5 +678,69 @@ SELECT a FROM t1 WHERE (a,b) in (SELECT @c,@d);
DROP TABLE t1;
--echo #
+--echo # MDEV-23384: Server crashes in subselect_indexsubquery_engine::print with optimizer trace enabled
+--echo #
+--echo # test subselect_indexsubquery_engine::print
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2);
+
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (3),(4);
+
+CREATE TABLE t3 (c INT);
+
+CREATE TABLE t4 (d INT);
+INSERT INTO t4 VALUES (5),(6);
+
+SET SESSION optimizer_trace= 'enabled=on';
+
+UPDATE t1, t2 SET t2.b = 1 WHERE
+(
+ WITH cte1 AS
+ (
+ SELECT MAX(c) FROM t3 WHERE c = 0 OR c IN
+ (
+ WITH cte2 AS
+ (
+ SELECT d FROM t4
+ )
+ SELECT * FROM cte2
+ )
+ )
+ SELECT * FROM cte1
+) IS NULL;
+
+# we don't actually need the trace, we are testing for a crash
+--echo # test subselect_uniquesubquery_engine::print
+
+CREATE TABLE t10 (a int, b int) ENGINE=myisam;
+
+CREATE TABLE t11 (a int, b int, unique(a));
+
+INSERT INTO t11 SELECT seq, seq FROM seq_1_to_10;
+
+CREATE TABLE t12 (a int, key(a));
+
+INSERT INTO t12 SELECT seq FROM seq_1_to_1000;
+
+SET SESSION optimizer_trace= 'enabled=on';
+
+SELECT * FROM t12 WHERE t12.a <
+(
+ SELECT b FROM
+ (
+ SELECT b FROM t10 WHERE a <3 or a in
+ (
+ SELECT a FROM t11 WHERE t11.b<t10.b
+ )
+ LIMIT 2
+ ) T
+);
+
+# Cleanup
+DROP TABLE t1, t2, t3, t4, t10, t11, t12;
+
+--echo #
--echo # End of 10.4 tests
--echo #
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 461bd9fb144..a8a518451ec 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -4537,7 +4537,7 @@ void subselect_uniquesubquery_engine::print(String *str,
str->append(STRING_WITH_LEN("<primary_index_lookup>("));
tab->ref.items[0]->print(str, query_type);
str->append(STRING_WITH_LEN(" in "));
- if (tab->table->s->table_category == TABLE_CATEGORY_TEMPORARY)
+ if (tab->tab_list->table->s->table_category == TABLE_CATEGORY_TEMPORARY)
{
/*
Temporary tables' names change across runs, so they can't be used for
@@ -4546,8 +4546,8 @@ void subselect_uniquesubquery_engine::print(String *str,
str->append(STRING_WITH_LEN("<temporary table>"));
}
else
- str->append(&tab->table->s->table_name);
- KEY *key_info= tab->table->key_info+ tab->ref.key;
+ str->append(&tab->tab_list->table->s->table_name);
+ KEY *key_info= tab->tab_list->table->key_info+ tab->ref.key;
str->append(STRING_WITH_LEN(" on "));
str->append(&key_info->name);
if (cond)
@@ -4588,8 +4588,9 @@ void subselect_indexsubquery_engine::print(String *str,
str->append(STRING_WITH_LEN("<index_lookup>("));
tab->ref.items[0]->print(str, query_type);
str->append(STRING_WITH_LEN(" in "));
- str->append(tab->table->s->table_name.str, tab->table->s->table_name.length);
- KEY *key_info= tab->table->key_info+ tab->ref.key;
+ str->append(tab->tab_list->table->s->table_name.str,
+ tab->tab_list->table->s->table_name.length);
+ KEY *key_info= tab->tab_list->table->key_info+ tab->ref.key;
str->append(STRING_WITH_LEN(" on "));
str->append(&key_info->name);
if (check_null)
@@ -5264,11 +5265,15 @@ subselect_hash_sj_engine::make_unique_engine()
- this JOIN_TAB has no corresponding JOIN (and doesn't need one), and
- here we initialize only those members that are used by
subselect_uniquesubquery_engine, so these objects are incomplete.
+ tab->tab_list is used in ::print, it needs initialization too.
*/
- if (!(tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB))))
+ if (!(tab= (JOIN_TAB*) thd->calloc(sizeof(JOIN_TAB))))
DBUG_RETURN(NULL);
- tab->table= tmp_table;
+ if (!(tab->tab_list= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
+ DBUG_RETURN(NULL);
+
+ tab->table= tab->tab_list->table= tmp_table;
tab->preread_init_done= FALSE;
tab->ref.tmp_table_index_lookup_init(thd, tmp_key, it, FALSE);