Commit 3f641968 authored by Sergey Vojtovich's avatar Sergey Vojtovich

BUG#51866 - crash with repair by sort and fulltext keys

Repairing MyISAM table with fulltext indexes and low
myisam_sort_buffer_size may crash the server.

Estimation of number of index entries was done incorrectly,
causing further assertion failure or server crash.

Docs note: min value for myisam_sort_buffer_size has been
changed from 4 to 4096.
parent 9ecdd588
...@@ -631,4 +631,17 @@ CREATE TABLE t1(a CHAR(1),FULLTEXT(a)); ...@@ -631,4 +631,17 @@ CREATE TABLE t1(a CHAR(1),FULLTEXT(a));
SELECT 1 FROM t1 WHERE MATCH(a) AGAINST ('') AND ROW(a,a) > ROW(1,1); SELECT 1 FROM t1 WHERE MATCH(a) AGAINST ('') AND ROW(a,a) > ROW(1,1);
1 1
DROP TABLE t1; DROP TABLE t1;
#
# BUG#51866 - crash with repair by sort and fulltext keys
#
CREATE TABLE t1(a CHAR(4), FULLTEXT(a));
INSERT INTO t1 VALUES('aaaa');
SET myisam_sort_buffer_size=4;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4'
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair status OK
SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size;
DROP TABLE t1;
End of 5.1 tests End of 5.1 tests
...@@ -2313,6 +2313,8 @@ INSERT INTO t1 SELECT a+1280,b FROM t1; ...@@ -2313,6 +2313,8 @@ INSERT INTO t1 SELECT a+1280,b FROM t1;
INSERT INTO t1 SELECT a+2560,b FROM t1; INSERT INTO t1 SELECT a+2560,b FROM t1;
INSERT INTO t1 SELECT a+5120,b FROM t1; INSERT INTO t1 SELECT a+5120,b FROM t1;
SET myisam_sort_buffer_size=4; SET myisam_sort_buffer_size=4;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4'
REPAIR TABLE t1; REPAIR TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 repair error myisam_sort_buffer_size is too small test.t1 repair error myisam_sort_buffer_size is too small
...@@ -2363,6 +2365,8 @@ CREATE TABLE t1(a CHAR(255), KEY(a)); ...@@ -2363,6 +2365,8 @@ CREATE TABLE t1(a CHAR(255), KEY(a));
SELECT * FROM t1, t1 AS a1; SELECT * FROM t1, t1 AS a1;
a a a a
SET myisam_sort_buffer_size=4; SET myisam_sort_buffer_size=4;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4'
INSERT INTO t1 VALUES INSERT INTO t1 VALUES
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),
......
...@@ -523,6 +523,8 @@ select @@max_user_connections; ...@@ -523,6 +523,8 @@ select @@max_user_connections;
100 100
set global max_write_lock_count=100; set global max_write_lock_count=100;
set myisam_sort_buffer_size=100; set myisam_sort_buffer_size=100;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '100'
set global net_buffer_length=100; set global net_buffer_length=100;
Warnings: Warnings:
Warning 1292 Truncated incorrect net_buffer_length value: '100' Warning 1292 Truncated incorrect net_buffer_length value: '100'
......
...@@ -8,11 +8,15 @@ SELECT @start_session_value; ...@@ -8,11 +8,15 @@ SELECT @start_session_value;
8388608 8388608
'#--------------------FN_DYNVARS_005_01-------------------------#' '#--------------------FN_DYNVARS_005_01-------------------------#'
SET @@global.myisam_sort_buffer_size = 100; SET @@global.myisam_sort_buffer_size = 100;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '100'
SET @@global.myisam_sort_buffer_size = DEFAULT; SET @@global.myisam_sort_buffer_size = DEFAULT;
SELECT @@global.myisam_sort_buffer_size ; SELECT @@global.myisam_sort_buffer_size ;
@@global.myisam_sort_buffer_size @@global.myisam_sort_buffer_size
8388608 8388608
SET @@session.myisam_sort_buffer_size = 200; SET @@session.myisam_sort_buffer_size = 200;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '200'
SET @@session.myisam_sort_buffer_size = DEFAULT; SET @@session.myisam_sort_buffer_size = DEFAULT;
SELECT @@session.myisam_sort_buffer_size ; SELECT @@session.myisam_sort_buffer_size ;
@@session.myisam_sort_buffer_size @@session.myisam_sort_buffer_size
...@@ -28,9 +32,11 @@ SELECT @@session.myisam_sort_buffer_size = 8388608; ...@@ -28,9 +32,11 @@ SELECT @@session.myisam_sort_buffer_size = 8388608;
1 1
'#--------------------FN_DYNVARS_005_03-------------------------#' '#--------------------FN_DYNVARS_005_03-------------------------#'
SET @@global.myisam_sort_buffer_size = 4; SET @@global.myisam_sort_buffer_size = 4;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4'
SELECT @@global.myisam_sort_buffer_size ; SELECT @@global.myisam_sort_buffer_size ;
@@global.myisam_sort_buffer_size @@global.myisam_sort_buffer_size
4 4096
SET @@global.myisam_sort_buffer_size = 4294967295; SET @@global.myisam_sort_buffer_size = 4294967295;
SELECT @@global.myisam_sort_buffer_size ; SELECT @@global.myisam_sort_buffer_size ;
@@global.myisam_sort_buffer_size @@global.myisam_sort_buffer_size
...@@ -41,9 +47,11 @@ SELECT @@global.myisam_sort_buffer_size ; ...@@ -41,9 +47,11 @@ SELECT @@global.myisam_sort_buffer_size ;
655354 655354
'#--------------------FN_DYNVARS_005_04-------------------------#' '#--------------------FN_DYNVARS_005_04-------------------------#'
SET @@session.myisam_sort_buffer_size = 4; SET @@session.myisam_sort_buffer_size = 4;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4'
SELECT @@session.myisam_sort_buffer_size ; SELECT @@session.myisam_sort_buffer_size ;
@@session.myisam_sort_buffer_size @@session.myisam_sort_buffer_size
4 4096
SET @@session.myisam_sort_buffer_size = 4294967295; SET @@session.myisam_sort_buffer_size = 4294967295;
SELECT @@session.myisam_sort_buffer_size ; SELECT @@session.myisam_sort_buffer_size ;
@@session.myisam_sort_buffer_size @@session.myisam_sort_buffer_size
...@@ -58,13 +66,13 @@ Warnings: ...@@ -58,13 +66,13 @@ Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0' Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0'
SELECT @@global.myisam_sort_buffer_size ; SELECT @@global.myisam_sort_buffer_size ;
@@global.myisam_sort_buffer_size @@global.myisam_sort_buffer_size
4 4096
SET @@global.myisam_sort_buffer_size = -1024; SET @@global.myisam_sort_buffer_size = -1024;
Warnings: Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '-1024' Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '-1024'
SELECT @@global.myisam_sort_buffer_size ; SELECT @@global.myisam_sort_buffer_size ;
@@global.myisam_sort_buffer_size @@global.myisam_sort_buffer_size
4 4096
SET @@global.myisam_sort_buffer_size = 429496729533; SET @@global.myisam_sort_buffer_size = 429496729533;
Warnings: Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '429496729533' Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '429496729533'
...@@ -101,28 +109,28 @@ Warnings: ...@@ -101,28 +109,28 @@ Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0' Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0'
SELECT @@session.myisam_sort_buffer_size ; SELECT @@session.myisam_sort_buffer_size ;
@@session.myisam_sort_buffer_size @@session.myisam_sort_buffer_size
4 4096
SET @@session.myisam_sort_buffer_size = -2; SET @@session.myisam_sort_buffer_size = -2;
Warnings: Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '-2' Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '-2'
SELECT @@session.myisam_sort_buffer_size ; SELECT @@session.myisam_sort_buffer_size ;
@@session.myisam_sort_buffer_size @@session.myisam_sort_buffer_size
4 4096
SET @@session.myisam_sort_buffer_size = 65530.34.; SET @@session.myisam_sort_buffer_size = 65530.34.;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.' at line 1
SELECT @@session.myisam_sort_buffer_size ; SELECT @@session.myisam_sort_buffer_size ;
@@session.myisam_sort_buffer_size @@session.myisam_sort_buffer_size
4 4096
SET @@session.myisam_sort_buffer_size = test; SET @@session.myisam_sort_buffer_size = test;
ERROR 42000: Incorrect argument type to variable 'myisam_sort_buffer_size' ERROR 42000: Incorrect argument type to variable 'myisam_sort_buffer_size'
SELECT @@session.myisam_sort_buffer_size ; SELECT @@session.myisam_sort_buffer_size ;
@@session.myisam_sort_buffer_size @@session.myisam_sort_buffer_size
4 4096
SET @@session.myisam_sort_buffer_size = "test"; SET @@session.myisam_sort_buffer_size = "test";
ERROR 42000: Incorrect argument type to variable 'myisam_sort_buffer_size' ERROR 42000: Incorrect argument type to variable 'myisam_sort_buffer_size'
SELECT @@session.myisam_sort_buffer_size ; SELECT @@session.myisam_sort_buffer_size ;
@@session.myisam_sort_buffer_size @@session.myisam_sort_buffer_size
4 4096
'#------------------FN_DYNVARS_005_06-----------------------#' '#------------------FN_DYNVARS_005_06-----------------------#'
SELECT @@global.myisam_sort_buffer_size = VARIABLE_VALUE SELECT @@global.myisam_sort_buffer_size = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
...@@ -141,20 +149,24 @@ Warnings: ...@@ -141,20 +149,24 @@ Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '1' Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '1'
SELECT @@global.myisam_sort_buffer_size ; SELECT @@global.myisam_sort_buffer_size ;
@@global.myisam_sort_buffer_size @@global.myisam_sort_buffer_size
4 4096
SET @@global.myisam_sort_buffer_size = FALSE; SET @@global.myisam_sort_buffer_size = FALSE;
Warnings: Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0' Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0'
SELECT @@global.myisam_sort_buffer_size ; SELECT @@global.myisam_sort_buffer_size ;
@@global.myisam_sort_buffer_size @@global.myisam_sort_buffer_size
4 4096
'#---------------------FN_DYNVARS_001_09----------------------#' '#---------------------FN_DYNVARS_001_09----------------------#'
SET @@global.myisam_sort_buffer_size = 10; SET @@global.myisam_sort_buffer_size = 10;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '10'
SELECT @@myisam_sort_buffer_size = @@global.myisam_sort_buffer_size ; SELECT @@myisam_sort_buffer_size = @@global.myisam_sort_buffer_size ;
@@myisam_sort_buffer_size = @@global.myisam_sort_buffer_size @@myisam_sort_buffer_size = @@global.myisam_sort_buffer_size
0 1
'#---------------------FN_DYNVARS_001_10----------------------#' '#---------------------FN_DYNVARS_001_10----------------------#'
SET @@myisam_sort_buffer_size = 100; SET @@myisam_sort_buffer_size = 100;
Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '100'
SELECT @@myisam_sort_buffer_size = @@local.myisam_sort_buffer_size ; SELECT @@myisam_sort_buffer_size = @@local.myisam_sort_buffer_size ;
@@myisam_sort_buffer_size = @@local.myisam_sort_buffer_size @@myisam_sort_buffer_size = @@local.myisam_sort_buffer_size
1 1
...@@ -167,7 +179,7 @@ Warnings: ...@@ -167,7 +179,7 @@ Warnings:
Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '1' Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '1'
SELECT @@myisam_sort_buffer_size ; SELECT @@myisam_sort_buffer_size ;
@@myisam_sort_buffer_size @@myisam_sort_buffer_size
4 4096
SELECT local.myisam_sort_buffer_size ; SELECT local.myisam_sort_buffer_size ;
ERROR 42S02: Unknown table 'local' in field list ERROR 42S02: Unknown table 'local' in field list
SELECT session.myisam_sort_buffer_size ; SELECT session.myisam_sort_buffer_size ;
......
...@@ -575,5 +575,14 @@ CREATE TABLE t1(a CHAR(1),FULLTEXT(a)); ...@@ -575,5 +575,14 @@ CREATE TABLE t1(a CHAR(1),FULLTEXT(a));
SELECT 1 FROM t1 WHERE MATCH(a) AGAINST ('') AND ROW(a,a) > ROW(1,1); SELECT 1 FROM t1 WHERE MATCH(a) AGAINST ('') AND ROW(a,a) > ROW(1,1);
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # BUG#51866 - crash with repair by sort and fulltext keys
--echo #
CREATE TABLE t1(a CHAR(4), FULLTEXT(a));
INSERT INTO t1 VALUES('aaaa');
SET myisam_sort_buffer_size=4;
REPAIR TABLE t1;
SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size;
DROP TABLE t1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -6858,7 +6858,7 @@ The minimum value for this variable is 4096.", ...@@ -6858,7 +6858,7 @@ The minimum value for this variable is 4096.",
"The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.",
(uchar**) &global_system_variables.myisam_sort_buff_size, (uchar**) &global_system_variables.myisam_sort_buff_size,
(uchar**) &max_system_variables.myisam_sort_buff_size, 0, (uchar**) &max_system_variables.myisam_sort_buff_size, 0,
GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0}, GET_ULONG, REQUIRED_ARG, 8192 * 1024, 4096, ~0L, 0, 1, 0},
{"myisam_use_mmap", OPT_MYISAM_USE_MMAP, {"myisam_use_mmap", OPT_MYISAM_USE_MMAP,
"Use memory mapping for reading and writing MyISAM tables.", "Use memory mapping for reading and writing MyISAM tables.",
(uchar**) &opt_myisam_use_mmap, (uchar**) &opt_myisam_use_mmap,
......
...@@ -2396,10 +2396,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -2396,10 +2396,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
/* /*
fulltext indexes may have much more entries than the fulltext indexes may have much more entries than the
number of rows in the table. We estimate the number here. number of rows in the table. We estimate the number here.
Note, built-in parser is always nr. 0 - see ftparser_call_initializer()
*/ */
if (sort_param.keyinfo->ftkey_nr == 0) if (sort_param.keyinfo->parser == &ft_default_parser)
{ {
/* /*
for built-in parser the number of generated index entries for built-in parser the number of generated index entries
...@@ -2416,8 +2414,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -2416,8 +2414,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
so, we'll use all the sort memory and start from ~10 buffpeks. so, we'll use all the sort memory and start from ~10 buffpeks.
(see _create_index_by_sort) (see _create_index_by_sort)
*/ */
sort_info.max_records= sort_info.max_records= 10 *
10*param->sort_buffer_length/sort_param.key_length; max(param->sort_buffer_length, MIN_SORT_BUFFER) /
sort_param.key_length;
} }
sort_param.key_read=sort_ft_key_read; sort_param.key_read=sort_ft_key_read;
......
...@@ -28,13 +28,11 @@ ...@@ -28,13 +28,11 @@
/* static variables */ /* static variables */
#undef MIN_SORT_MEMORY
#undef MYF_RW #undef MYF_RW
#undef DISK_BUFFER_SIZE #undef DISK_BUFFER_SIZE
#define MERGEBUFF 15 #define MERGEBUFF 15
#define MERGEBUFF2 31 #define MERGEBUFF2 31
#define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD)
#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
#define DISK_BUFFER_SIZE (IO_SIZE*16) #define DISK_BUFFER_SIZE (IO_SIZE*16)
...@@ -131,12 +129,12 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -131,12 +129,12 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
sort_keys= (uchar **) NULL; error= 1; sort_keys= (uchar **) NULL; error= 1;
maxbuffer=1; maxbuffer=1;
memavl=max(sortbuff_size,MIN_SORT_MEMORY); memavl= max(sortbuff_size, MIN_SORT_BUFFER);
records= info->sort_info->max_records; records= info->sort_info->max_records;
sort_length= info->key_length; sort_length= info->key_length;
LINT_INIT(keys); LINT_INIT(keys);
while (memavl >= MIN_SORT_MEMORY) while (memavl >= MIN_SORT_BUFFER)
{ {
if ((records < UINT_MAX32) && if ((records < UINT_MAX32) &&
((my_off_t) (records + 1) * ((my_off_t) (records + 1) *
...@@ -171,10 +169,10 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -171,10 +169,10 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
break; break;
} }
old_memavl=memavl; old_memavl=memavl;
if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY) if ((memavl= memavl/4*3) < MIN_SORT_BUFFER && old_memavl > MIN_SORT_BUFFER)
memavl=MIN_SORT_MEMORY; memavl= MIN_SORT_BUFFER;
} }
if (memavl < MIN_SORT_MEMORY) if (memavl < MIN_SORT_BUFFER)
{ {
mi_check_print_error(info->sort_info->param,"MyISAM sort buffer too small"); /* purecov: tested */ mi_check_print_error(info->sort_info->param,"MyISAM sort buffer too small"); /* purecov: tested */
goto err; /* purecov: tested */ goto err; /* purecov: tested */
...@@ -348,12 +346,12 @@ pthread_handler_t thr_find_all_keys(void *arg) ...@@ -348,12 +346,12 @@ pthread_handler_t thr_find_all_keys(void *arg)
bzero((char*) &sort_param->unique, sizeof(sort_param->unique)); bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
sort_keys= (uchar **) NULL; sort_keys= (uchar **) NULL;
memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY); memavl= max(sort_param->sortbuff_size, MIN_SORT_BUFFER);
idx= (uint)sort_param->sort_info->max_records; idx= (uint)sort_param->sort_info->max_records;
sort_length= sort_param->key_length; sort_length= sort_param->key_length;
maxbuffer= 1; maxbuffer= 1;
while (memavl >= MIN_SORT_MEMORY) while (memavl >= MIN_SORT_BUFFER)
{ {
if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <=
(my_off_t) memavl) (my_off_t) memavl)
...@@ -391,11 +389,11 @@ pthread_handler_t thr_find_all_keys(void *arg) ...@@ -391,11 +389,11 @@ pthread_handler_t thr_find_all_keys(void *arg)
break; break;
} }
old_memavl= memavl; old_memavl= memavl;
if ((memavl= memavl/4*3) < MIN_SORT_MEMORY && if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER &&
old_memavl > MIN_SORT_MEMORY) old_memavl > MIN_SORT_BUFFER)
memavl= MIN_SORT_MEMORY; memavl= MIN_SORT_BUFFER;
} }
if (memavl < MIN_SORT_MEMORY) if (memavl < MIN_SORT_BUFFER)
{ {
mi_check_print_error(sort_param->sort_info->param, mi_check_print_error(sort_param->sort_info->param,
"MyISAM sort buffer too small"); "MyISAM sort buffer too small");
...@@ -569,7 +567,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) ...@@ -569,7 +567,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
if (!mergebuf) if (!mergebuf)
{ {
length=param->sort_buffer_length; length=param->sort_buffer_length;
while (length >= MIN_SORT_MEMORY) while (length >= MIN_SORT_BUFFER)
{ {
if ((mergebuf= my_malloc(length, MYF(0)))) if ((mergebuf= my_malloc(length, MYF(0))))
break; break;
......
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