MDEV-23294 Segfault or assertion upon MyISAM repair

When computing vcol expression some items use current_thd and that was
not set in MyISAM repair thread. Since all the repair threads belong
to one connection and items should not write into THD we can utilize
table THD for that.
This commit is contained in:
Aleksey Midenkov 2023-11-09 16:26:11 +03:00
parent 74883f5e2f
commit ebb6f57568
5 changed files with 83 additions and 0 deletions

View file

@ -117,6 +117,7 @@ typedef struct st_handler_check_param
uint progress_counter; /* How often to call _report_progress() */
ulonglong progress, max_progress;
void (*init_fix_record)(void *);
int (*fix_record)(struct st_myisam_info *info, uchar *record, int keynum);
mysql_mutex_t print_msg_mutex;

View file

@ -418,3 +418,40 @@ create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk
insert into t2 (pk) select a from t1;
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
drop tables t1, t2;
#
# MDEV-23294 Segfault or assertion upon MyISAM repair
#
set @old_mode= @@sql_mode;
set @old_myisam_repair_threads= @@myisam_repair_threads;
set sql_mode='', myisam_repair_threads=2;
create table t (a binary,b blob,c blob as (concat (a,b)),h char,index (c)) engine=innodb;
Warnings:
Warning 1286 Unknown storage engine 'innodb'
Warning 1266 Using storage engine MyISAM for table 't'
Note 1071 Specified key was too long; max key length is 1000 bytes
insert into t values (0,0,default,0);
create table ti like t;
alter table ti engine=myisam;
insert into ti select * from t;
Warnings:
Warning 1906 The value specified for generated column 'c' in table 'ti' has been ignored
drop tables ti, t;
create table t (id int,a varchar(1),b varchar(1),c varchar(1) generated always as (concat (a,b)),key(c)) engine=myisam;
insert into t values (0,0,9687,0);
Warnings:
Warning 1265 Data truncated for column 'b' at row 1
Warning 1906 The value specified for generated column 'c' in table 't' has been ignored
Warning 1265 Data truncated for column 'c' at row 1
repair table t quick;
Table Op Msg_type Msg_text
test.t repair status OK
drop table t;
create table t1 (b varchar(1024), c char(3), unique(b,c)) engine=myisam;
insert into t1 values ('foo','baz');
alter table t1 disable keys;
set session myisam_repair_threads= 2;
insert into t1 select 'qux';
ERROR 21S01: Column count doesn't match value count at row 1
drop table t1;
set sql_mode= @old_mode;
set myisam_repair_threads= @old_myisam_repair_threads;

View file

@ -313,3 +313,32 @@ create or replace table t2 (pk int, b int, c int as (b) virtual, primary key (pk
--error ER_DUP_ENTRY
insert into t2 (pk) select a from t1;
drop tables t1, t2;
--echo #
--echo # MDEV-23294 Segfault or assertion upon MyISAM repair
--echo #
set @old_mode= @@sql_mode;
set @old_myisam_repair_threads= @@myisam_repair_threads;
set sql_mode='', myisam_repair_threads=2;
create table t (a binary,b blob,c blob as (concat (a,b)),h char,index (c)) engine=innodb;
insert into t values (0,0,default,0);
create table ti like t;
alter table ti engine=myisam;
insert into ti select * from t;
drop tables ti, t;
create table t (id int,a varchar(1),b varchar(1),c varchar(1) generated always as (concat (a,b)),key(c)) engine=myisam;
insert into t values (0,0,9687,0);
repair table t quick;
drop table t;
create table t1 (b varchar(1024), c char(3), unique(b,c)) engine=myisam;
insert into t1 values ('foo','baz');
alter table t1 disable keys;
set session myisam_repair_threads= 2;
--error ER_WRONG_VALUE_COUNT_ON_ROW
insert into t1 select 'qux';
# cleanup
drop table t1;
set sql_mode= @old_mode;
set myisam_repair_threads= @old_myisam_repair_threads;

View file

@ -709,6 +709,16 @@ my_bool mi_killed_in_mariadb(MI_INFO *info)
return (((TABLE*) (info->external_ref))->in_use->killed != 0);
}
static void init_compute_vcols(void *table)
{
/*
To evaluate vcols we must have current_thd set.
This will set current_thd in all threads to the same THD, but it's
safe, because vcols are always evaluated under info->s->intern_lock.
*/
set_current_thd(static_cast<TABLE *>(table)->in_use);
}
static int compute_vcols(MI_INFO *info, uchar *record, int keynum)
{
/* This mutex is needed for parallel repair */
@ -1010,6 +1020,7 @@ void ha_myisam::setup_vcols_for_repair(HA_CHECK *param)
}
DBUG_ASSERT(file->s->base.reclength < file->s->vreclength ||
!table->s->stored_fields);
param->init_fix_record= init_compute_vcols;
param->fix_record= compute_vcols;
table->use_all_columns();
}

View file

@ -503,6 +503,11 @@ pthread_handler_t thr_find_all_keys(void *arg)
{
MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg;
my_bool error= FALSE;
MI_SORT_INFO *si= sort_param->sort_info;
if (si->param->init_fix_record)
si->param->init_fix_record(si->info->external_ref);
/* If my_thread_init fails */
if (my_thread_init() || thr_find_all_keys_exec(sort_param))
error= TRUE;