diff options
author | Sergei Petrunia <sergey@mariadb.com> | 2023-04-26 21:41:49 +0300 |
---|---|---|
committer | Sergei Petrunia <sergey@mariadb.com> | 2023-04-27 13:48:43 +0300 |
commit | cbd36645b7c4ba0ef0db97fd640cf89326d0746e (patch) | |
tree | fd31ea3b952970cc76c9005e9632abc839fac558 | |
parent | 9c287c0a90fcb6637417bd118f62c78de78f75ee (diff) | |
download | mariadb-git-bb-11.0-MDEV-31022-variant2.tar.gz |
MDEV-31022 SIGSEGV in maria_create from create_internal_tmp_tablebb-11.0-MDEV-31022-variant2
Make create_internal_tmp_table() handle the case where the
created table has multiple indexes.
-rw-r--r-- | mysql-test/main/derived.result | 28 | ||||
-rw-r--r-- | mysql-test/main/derived.test | 24 | ||||
-rw-r--r-- | sql/sql_select.cc | 50 |
3 files changed, 86 insertions, 16 deletions
diff --git a/mysql-test/main/derived.result b/mysql-test/main/derived.result index 112a72a2bf6..b5b4341ce5e 100644 --- a/mysql-test/main/derived.result +++ b/mysql-test/main/derived.result @@ -1476,5 +1476,33 @@ a 2 drop table t1; # +# MDEV-31022: SIGSEGV in maria_create from create_internal_tmp_table +# keydef incorrectly allocated on the stack in create_internal_tmp_table() +# +CREATE TABLE t1 (c CHAR(1) NULL) ENGINE=MyISAM; +INSERT INTO t1 (c) VALUES (1); +SET statement +optimizer_where_cost=1, +big_tables=1, +in_predicate_conversion_threshold=2 +FOR +SELECT * FROM t1 WHERE c IN ('',''); +c +Warnings: +Warning 1287 '@@big_tables' is deprecated and will be removed in a future release +Warning 1287 '@@big_tables' is deprecated and will be removed in a future release +SET statement +optimizer_where_cost=1, +big_tables=1, +in_predicate_conversion_threshold=2, +sql_mode='' +FOR +SELECT * FROM t1 WHERE c IN ('',''); +c +Warnings: +Warning 1287 '@@big_tables' is deprecated and will be removed in a future release +Warning 1287 '@@big_tables' is deprecated and will be removed in a future release +DROP TABLE t1; +# # End of 11.0 tests # diff --git a/mysql-test/main/derived.test b/mysql-test/main/derived.test index e5f01e15821..b26472d41c0 100644 --- a/mysql-test/main/derived.test +++ b/mysql-test/main/derived.test @@ -1244,5 +1244,29 @@ SELECT a FROM t1 WHERE a IN ( 1, 1, 2, 194 ); drop table t1; --echo # +--echo # MDEV-31022: SIGSEGV in maria_create from create_internal_tmp_table +--echo # keydef incorrectly allocated on the stack in create_internal_tmp_table() +--echo # + +CREATE TABLE t1 (c CHAR(1) NULL) ENGINE=MyISAM; +INSERT INTO t1 (c) VALUES (1); +SET statement + optimizer_where_cost=1, + big_tables=1, + in_predicate_conversion_threshold=2 +FOR +SELECT * FROM t1 WHERE c IN ('',''); + +SET statement + optimizer_where_cost=1, + big_tables=1, + in_predicate_conversion_threshold=2, + sql_mode='' +FOR +SELECT * FROM t1 WHERE c IN ('',''); + +DROP TABLE t1; + +--echo # --echo # End of 11.0 tests --echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 26987c9072e..7c384bf2959 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -21766,14 +21766,17 @@ bool open_tmp_table(TABLE *table) SYNOPSIS create_internal_tmp_table() table Table object that descrimes the table to be created - keyinfo Description of the index (there is always one index) + keyinfo Description of the index(es) start_recinfo engine's column descriptions recinfo INOUT End of engine's column descriptions options Option bits DESCRIPTION - Create an internal emporary table according to passed description. The is - assumed to have one unique index or constraint. + Create an internal temporary table according to passed description. The + table may have indexes: + - a unique index or constraint used to handle GROUP BY or DISTINCT, or + - a non-unique index created by derived_with_keys optimization + - or, starting from 11.0: both of the above. The passed array or TMP_ENGINE_COLUMNDEF structures must have this form: @@ -21791,20 +21794,35 @@ bool open_tmp_table(TABLE *table) */ -bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, +bool create_internal_tmp_table(TABLE *table, KEY *all_key_info, TMP_ENGINE_COLUMNDEF *start_recinfo, TMP_ENGINE_COLUMNDEF **recinfo, ulonglong options) { int error; - MARIA_KEYDEF keydef; + MARIA_KEYDEF *keydef= nullptr; MARIA_UNIQUEDEF uniquedef; TABLE_SHARE *share= table->s; MARIA_CREATE_INFO create_info; + uint keyno; DBUG_ENTER("create_internal_tmp_table"); + // Save the value of share->keys as it might be decremented when converting a + // key to a unique constraint. + uint original_keys= share->keys; + if (share->keys) - { // Get keys for ni_create + { + if (!(keydef= (MARIA_KEYDEF*) alloc_root(&table->mem_root, + sizeof(*keydef) * share->keys))) + goto err; + bzero(keydef, sizeof(*keydef) * share->keys); + } + + for (keyno= 0; keyno < original_keys; keyno++) + { + KEY *keyinfo= all_key_info + keyno; + bool using_unique_constraint=0; HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&table->mem_root, sizeof(*seg) * keyinfo->user_defined_key_parts); @@ -21830,9 +21848,10 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, } /* Can't create a key; Make a unique constraint instead of a key */ - share->keys= 0; - share->key_parts= share->ext_key_parts= 0; - share->uniques= 1; + share->keys--; + share->key_parts -= keyinfo->user_defined_key_parts; + share->ext_key_parts -= keyinfo->user_defined_key_parts; + share->uniques=1; using_unique_constraint=1; bzero((char*) &uniquedef,sizeof(uniquedef)); uniquedef.keysegs=keyinfo->user_defined_key_parts; @@ -21853,10 +21872,9 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, else { /* Create a key */ - bzero((char*) &keydef,sizeof(keydef)); - keydef.flag= keyinfo->flags & HA_NOSAME; - keydef.keysegs= keyinfo->user_defined_key_parts; - keydef.seg= seg; + keydef[keyno].flag= keyinfo->flags & HA_NOSAME; + keydef[keyno].keysegs= keyinfo->user_defined_key_parts; + keydef[keyno].seg= seg; } for (uint i=0; i < keyinfo->user_defined_key_parts ; i++,seg++) { @@ -21893,11 +21911,11 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, on INSERT be regarded at the same value */ if (!using_unique_constraint) - keydef.flag|= HA_NULL_ARE_EQUAL; + keydef[keyno].flag|= HA_NULL_ARE_EQUAL; } } if (share->keys) - keyinfo->index_flags= table->file->index_flags(0, 0, 1); + keyinfo->index_flags= table->file->index_flags(keyno, 0, 1); } bzero((char*) &create_info,sizeof(create_info)); create_info.data_file_length= table->in_use->variables.tmp_disk_table_size; @@ -21943,7 +21961,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, } if (unlikely((error= maria_create(share->path.str, file_type, share->keys, - &keydef, (uint) (*recinfo-start_recinfo), + keydef, (uint) (*recinfo-start_recinfo), start_recinfo, share->uniques, &uniquedef, &create_info, create_flags)))) { |