Commit fe9092a8 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-35029 ASAN errors in Lex_ident<Compare_ident_ci>::is_valid_ident upon DDL...

MDEV-35029 ASAN errors in Lex_ident<Compare_ident_ci>::is_valid_ident upon DDL on table with vector index

in ALTER TABLE or CREATE TABLE LIKE, a create a copy of key->option_list,
because it can be extended later on the thd->mem_root, so it has
to be a copy
parent e537e447
...@@ -24,3 +24,18 @@ set global mhnsw_cache_size = 1048576; ...@@ -24,3 +24,18 @@ set global mhnsw_cache_size = 1048576;
insert into t values (2,x'00000000'); insert into t values (2,x'00000000');
drop table t; drop table t;
set global mhnsw_cache_size = default; set global mhnsw_cache_size = default;
#
# MDEV-35029 ASAN errors in Lex_ident<Compare_ident_ci>::is_valid_ident upon DDL on table with vector index
#
create table t (a int, v blob not null, vector key (v) distance_function=euclidean);
show create table t;
Table Create Table
t CREATE TABLE `t` (
`a` int(11) DEFAULT NULL,
`v` blob NOT NULL,
VECTOR KEY `v` (`v`) `distance_function`=euclidean
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci
set session mhnsw_max_edges_per_node = @@mhnsw_max_edges_per_node + 1;
create table t2 like t;
alter table t force;
drop table t, t2;
...@@ -31,3 +31,13 @@ insert into t values (2,x'00000000'); ...@@ -31,3 +31,13 @@ insert into t values (2,x'00000000');
drop table t; drop table t;
set global mhnsw_cache_size = default; set global mhnsw_cache_size = default;
--echo #
--echo # MDEV-35029 ASAN errors in Lex_ident<Compare_ident_ci>::is_valid_ident upon DDL on table with vector index
--echo #
create table t (a int, v blob not null, vector key (v) distance_function=euclidean);
show create table t;
set session mhnsw_max_edges_per_node = @@mhnsw_max_edges_per_node + 1;
create table t2 like t;
alter table t force;
drop table t, t2;
...@@ -8321,6 +8321,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8321,6 +8321,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
List<Key> new_key_list; List<Key> new_key_list;
List<FOREIGN_KEY_INFO> fk_list; List<FOREIGN_KEY_INFO> fk_list;
List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list); List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
MEM_ROOT *root= thd->mem_root;
/* /*
Create a deep copy of the list of visibility for indexes, as it will be Create a deep copy of the list of visibility for indexes, as it will be
...@@ -8328,9 +8329,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8328,9 +8329,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
*/ */
List<Alter_index_ignorability> List<Alter_index_ignorability>
alter_index_ignorability_list(alter_info->alter_index_ignorability_list, alter_index_ignorability_list(alter_info->alter_index_ignorability_list,
thd->mem_root); root);
list_copy_and_replace_each_value(alter_index_ignorability_list, thd->mem_root); list_copy_and_replace_each_value(alter_index_ignorability_list, root);
List_iterator<Alter_drop> drop_it(alter_info->drop_list); List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<Create_field> def_it(alter_info->create_list); List_iterator<Create_field> def_it(alter_info->create_list);
...@@ -8409,7 +8410,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8409,7 +8410,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
column_rename_param.db_name= table->s->db; column_rename_param.db_name= table->s->db;
column_rename_param.table_name= table->s->table_name; column_rename_param.table_name= table->s->table_name;
if (column_rename_param.fields.copy(&alter_info->create_list, thd->mem_root)) if (column_rename_param.fields.copy(&alter_info->create_list, root))
DBUG_RETURN(1); // OOM DBUG_RETURN(1); // OOM
restore_record(table, s->default_values); // Empty record for DEFAULT restore_record(table, s->default_values); // Empty record for DEFAULT
...@@ -8421,7 +8422,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8421,7 +8422,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
DBUG_RETURN(1); DBUG_RETURN(1);
if (merge_engine_options(table->s->option_list, create_info->option_list, if (merge_engine_options(table->s->option_list, create_info->option_list,
&create_info->option_list, thd->mem_root)) &create_info->option_list, root))
DBUG_RETURN(1); DBUG_RETURN(1);
table->file->get_foreign_key_list(thd, &fk_list); table->file->get_foreign_key_list(thd, &fk_list);
...@@ -8464,7 +8465,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8464,7 +8465,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
} }
if (table->s->tmp_table == NO_TMP_TABLE) if (table->s->tmp_table == NO_TMP_TABLE)
{ {
if (alter_info->drop_stat_fields.push_back(field, thd->mem_root)) if (alter_info->drop_stat_fields.push_back(field, root))
DBUG_RETURN(true); DBUG_RETURN(true);
} }
dropped_sys_vers_fields|= field->flags; dropped_sys_vers_fields|= field->flags;
...@@ -8488,7 +8489,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8488,7 +8489,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{ {
if (table->s->tmp_table == NO_TMP_TABLE) if (table->s->tmp_table == NO_TMP_TABLE)
{ {
if (alter_info->drop_stat_fields.push_back(field, thd->mem_root)) if (alter_info->drop_stat_fields.push_back(field, root))
DBUG_RETURN(true); DBUG_RETURN(true);
} }
continue; continue;
...@@ -8509,7 +8510,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8509,7 +8510,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
Note that columns with AFTER clauses are added to the end Note that columns with AFTER clauses are added to the end
of the list for now. Their positions will be corrected later. of the list for now. Their positions will be corrected later.
*/ */
new_create_list.push_back(def, thd->mem_root); new_create_list.push_back(def, root);
if (field->stored_in_db() != def->stored_in_db()) if (field->stored_in_db() != def->stored_in_db())
{ {
my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0)); my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0));
...@@ -8541,7 +8542,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8541,7 +8542,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
!(alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING)) !(alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING))
{ {
/* "dropping" a versioning field only hides it from the user */ /* "dropping" a versioning field only hides it from the user */
def= new (thd->mem_root) Create_field(thd, field, field); def= new (root) Create_field(thd, field, field);
def->invisible= INVISIBLE_SYSTEM; def->invisible= INVISIBLE_SYSTEM;
alter_info->flags|= ALTER_CHANGE_COLUMN; alter_info->flags|= ALTER_CHANGE_COLUMN;
if (field->flags & VERS_ROW_START) if (field->flags & VERS_ROW_START)
...@@ -8553,7 +8554,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8553,7 +8554,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
create_info->vers_info.period.end= create_info->vers_info.period.end=
create_info->vers_info.as_row.end= create_info->vers_info.as_row.end=
def->field_name= Vers_parse_info::default_end; def->field_name= Vers_parse_info::default_end;
new_create_list.push_back(def, thd->mem_root); new_create_list.push_back(def, root);
dropped_sys_vers_fields|= field->flags; dropped_sys_vers_fields|= field->flags;
drop_it.remove(); drop_it.remove();
} }
...@@ -8563,8 +8564,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8563,8 +8564,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
This field was not dropped and not changed, add it to the list This field was not dropped and not changed, add it to the list
for the new table. for the new table.
*/ */
def= new (thd->mem_root) Create_field(thd, field, field); def= new (root) Create_field(thd, field, field);
new_create_list.push_back(def, thd->mem_root); new_create_list.push_back(def, root);
alter_it.rewind(); // Change default if ALTER alter_it.rewind(); // Change default if ALTER
Alter_column *alter; Alter_column *alter;
while ((alter=alter_it++)) while ((alter=alter_it++))
...@@ -8610,8 +8611,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8610,8 +8611,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
else else
{ {
DBUG_ASSERT(field->invisible == INVISIBLE_SYSTEM); DBUG_ASSERT(field->invisible == INVISIBLE_SYSTEM);
def= new (thd->mem_root) Create_field(thd, field, field); def= new (root) Create_field(thd, field, field);
new_create_tail.push_back(def, thd->mem_root); new_create_tail.push_back(def, root);
} }
} }
...@@ -8670,11 +8671,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8670,11 +8671,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
} /* if (def->change.str) */ } /* if (def->change.str) */
} /* while (def) */ } /* while (def) */
} /* if (part_field_list || subpart_field_list) */ } /* if (part_field_list || subpart_field_list) */
// Force reopen because new column name is on thd->mem_root // Force reopen because new column name is on root
table->mark_table_for_reopen(); table->mark_table_for_reopen();
} /* if (part_info) */ } /* if (part_info) */
#endif #endif
// Force reopen because new column name is on thd->mem_root // Force reopen because new column name is on root
table->mark_table_for_reopen(); table->mark_table_for_reopen();
} }
...@@ -8738,7 +8739,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8738,7 +8739,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
alter_ctx->error_if_not_empty= TRUE; alter_ctx->error_if_not_empty= TRUE;
} }
if (!def->after.str) if (!def->after.str)
new_create_list.push_back(def, thd->mem_root); new_create_list.push_back(def, root);
else else
{ {
if (def->change.str) if (def->change.str)
...@@ -8765,7 +8766,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8765,7 +8766,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
} }
} }
if (def->after.str == first_keyword) if (def->after.str == first_keyword)
new_create_list.push_front(def, thd->mem_root); new_create_list.push_front(def, root);
else else
{ {
find_it.rewind(); find_it.rewind();
...@@ -8846,7 +8847,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8846,7 +8847,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{ {
if (table->s->tmp_table == NO_TMP_TABLE) if (table->s->tmp_table == NO_TMP_TABLE)
{ {
if (alter_info->add_stat_drop_index(key_info, FALSE, thd->mem_root)) if (alter_info->add_stat_drop_index(key_info, FALSE, root))
DBUG_RETURN(true); DBUG_RETURN(true);
if (primary_key) if (primary_key)
{ {
...@@ -8857,8 +8858,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8857,8 +8858,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
tab_key_info->user_defined_key_parts != tab_key_info->user_defined_key_parts !=
tab_key_info->ext_key_parts) tab_key_info->ext_key_parts)
{ {
if (alter_info->add_stat_drop_index(tab_key_info, TRUE, if (alter_info->add_stat_drop_index(tab_key_info, TRUE, root))
thd->mem_root))
DBUG_RETURN(true); DBUG_RETURN(true);
} }
} }
...@@ -8902,8 +8902,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -8902,8 +8902,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (cmp(&rename_key->old_name, &rename_key->new_name)) if (cmp(&rename_key->old_name, &rename_key->new_name))
{ {
/* Key was renamed */ /* Key was renamed */
alter_info->add_stat_rename_index(key_info, &rename_key->new_name, alter_info->add_stat_rename_index(key_info, &rename_key->new_name, root);
thd->mem_root);
} }
rename_key_it.remove(); rename_key_it.remove();
...@@ -9005,10 +9004,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -9005,10 +9004,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key_part_length= 0; // Use whole field key_part_length= 0; // Use whole field
} }
key_part_length /= kfield->charset()->mbmaxlen; key_part_length /= kfield->charset()->mbmaxlen;
Key_part_spec *kps= new (thd->mem_root) Key_part_spec(&cfield->field_name, Key_part_spec *kps= new (root) Key_part_spec(&cfield->field_name,
key_part_length, true); key_part_length, true);
kps->asc= !(key_part->key_part_flag & HA_REVERSE_SORT); kps->asc= !(key_part->key_part_flag & HA_REVERSE_SORT);
key_parts.push_back(kps, thd->mem_root); key_parts.push_back(kps, root);
if (!(cfield->invisible == INVISIBLE_SYSTEM && cfield->vers_sys_field())) if (!(cfield->invisible == INVISIBLE_SYSTEM && cfield->vers_sys_field()))
user_keyparts= true; user_keyparts= true;
} }
...@@ -9016,14 +9015,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -9016,14 +9015,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{ {
if (delete_index_stat) if (delete_index_stat)
{ {
if (alter_info->add_stat_drop_index(key_info, FALSE, thd->mem_root)) if (alter_info->add_stat_drop_index(key_info, FALSE, root))
DBUG_RETURN(true); DBUG_RETURN(true);
} }
else if (alter_ctx->modified_primary_key && else if (alter_ctx->modified_primary_key &&
key_info->user_defined_key_parts != key_info->ext_key_parts) key_info->user_defined_key_parts != key_info->ext_key_parts)
{ {
if (alter_info->add_stat_drop_index(key_info, FALSE, if (alter_info->add_stat_drop_index(key_info, FALSE, root))
thd->mem_root))
DBUG_RETURN(true); DBUG_RETURN(true);
} }
} }
...@@ -9042,6 +9040,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -9042,6 +9040,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
Key *key; Key *key;
enum Key::Keytype key_type; enum Key::Keytype key_type;
LEX_CSTRING tmp_name; LEX_CSTRING tmp_name;
engine_option_value *option_list;
bzero((char*) &key_create_info, sizeof(key_create_info)); bzero((char*) &key_create_info, sizeof(key_create_info));
if (key_info->algorithm == HA_KEY_ALG_LONG_HASH) if (key_info->algorithm == HA_KEY_ALG_LONG_HASH)
key_info->algorithm= HA_KEY_ALG_UNDEF; key_info->algorithm= HA_KEY_ALG_UNDEF;
...@@ -9101,15 +9101,18 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -9101,15 +9101,18 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
} }
} }
if (merge_engine_options(key_info->option_list, 0, &option_list, root))
goto err;
tmp_name= key_name; tmp_name= key_name;
/* We dont need LONG_UNIQUE_HASH_FIELD flag because it will be autogenerated */ /* We dont need LONG_UNIQUE_HASH_FIELD flag because it will be autogenerated */
key= new (thd->mem_root) Key(key_type, &tmp_name, &key_create_info, key= new (root) Key(key_type, &tmp_name, &key_create_info,
key_info->flags & HA_GENERATED_KEY, key_info->flags & HA_GENERATED_KEY, &key_parts,
&key_parts, key_info->option_list, DDL_options()); option_list, DDL_options());
key->without_overlaps= key_info->without_overlaps; key->without_overlaps= key_info->without_overlaps;
key->period= table->s->period.name; key->period= table->s->period.name;
key->old= true; key->old= true;
new_key_list.push_back(key, thd->mem_root); new_key_list.push_back(key, root);
} }
if (long_hash_key) if (long_hash_key)
{ {
...@@ -9130,15 +9133,15 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -9130,15 +9133,15 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
continue; continue;
List<Key_part_spec> cols, ref_cols; List<Key_part_spec> cols, ref_cols;
for (LEX_CSTRING &c : fk.foreign_fields) for (LEX_CSTRING &c : fk.foreign_fields)
cols.push_back(new (thd->mem_root) Key_part_spec(&c, 0)); cols.push_back(new (root) Key_part_spec(&c, 0));
for (LEX_CSTRING &c : fk.referenced_fields) for (LEX_CSTRING &c : fk.referenced_fields)
ref_cols.push_back(new (thd->mem_root) Key_part_spec(&c, 0)); ref_cols.push_back(new (root) Key_part_spec(&c, 0));
auto key= new (thd->mem_root) auto key= new (root)
Foreign_key(fk.foreign_id, &cols, fk.foreign_id, fk.referenced_db, Foreign_key(fk.foreign_id, &cols, fk.foreign_id, fk.referenced_db,
fk.referenced_table, &ref_cols, fk.delete_method, fk.update_method, fk.referenced_table, &ref_cols, fk.delete_method, fk.update_method,
Foreign_key::FK_MATCH_UNDEF, DDL_options()); Foreign_key::FK_MATCH_UNDEF, DDL_options());
key->old= true; key->old= true;
new_key_list.push_back(key, thd->mem_root); new_key_list.push_back(key, root);
} }
} }
{ {
...@@ -9148,7 +9151,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -9148,7 +9151,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (key->type == Key::FOREIGN_KEY && if (key->type == Key::FOREIGN_KEY &&
((Foreign_key *)key)->validate(new_create_list)) ((Foreign_key *)key)->validate(new_create_list))
goto err; goto err;
new_key_list.push_back(key, thd->mem_root); new_key_list.push_back(key, root);
if (key->name.str && if (key->name.str &&
key->name.streq(primary_key_name)) key->name.streq(primary_key_name))
{ {
...@@ -9253,10 +9256,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, ...@@ -9253,10 +9256,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{ {
check->expr->walk(&Item::rename_fields_processor, 1, check->expr->walk(&Item::rename_fields_processor, 1,
&column_rename_param); &column_rename_param);
// Force reopen because new column name is on thd->mem_root // Force reopen because new column name is on root
table->mark_table_for_reopen(); table->mark_table_for_reopen();
} }
new_constraint_list.push_back(check, thd->mem_root); new_constraint_list.push_back(check, root);
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment