Skip to content

Commit ac2b92c

Browse files
committed
MDEV-7912 multitable delete with wrongly set sort_buffer_size crashes in merge_buffers
Fixed overflow error that caused fewer bites to be allocated than necessary on Windows 64 bit. This is due to ulong being 32 bit on 64 bit Windows and 64 bit on 64 bit Linux.
1 parent 939a233 commit ac2b92c

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
set sql_mode="";
2+
drop table if exists t1,t2;
3+
Warnings:
4+
Note 1051 Unknown table 't1'
5+
Note 1051 Unknown table 't2'
6+
create table `t1` (`a` datetime not null) engine=InnoDB;
7+
create table `t2` (`a` int not null) engine=innodb;
8+
replace into t1 values (),();
9+
Warnings:
10+
Warning 1364 Field 'a' doesn't have a default value
11+
insert into t2 values(0);
12+
set session sort_buffer_size = 1024*1024*1024*1024;
13+
SET session debug_dbug= '+d,make_merge_buff_alloc_fail';
14+
delete d2 from t2 as d1, t1 as d2 where d1.a <=> d2.a;
15+
ERROR HY000: Out of memory (Needed 2 bytes)
16+
SET SESSION debug_dbug=DEFAULT;
17+
drop table t2;
18+
drop table t1;

mysql-test/t/uniques_crash-7912.test

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# MDEV-7912
2+
# multitable delete with wrongly set sort_buffer_size crashes in merge_buffers
3+
--source include/have_innodb.inc
4+
set sql_mode="";
5+
drop table if exists t1,t2;
6+
create table `t1` (`a` datetime not null) engine=InnoDB;
7+
create table `t2` (`a` int not null) engine=innodb;
8+
9+
replace into t1 values (),();
10+
insert into t2 values(0);
11+
set session sort_buffer_size = 1024*1024*1024*1024;
12+
SET session debug_dbug= '+d,make_merge_buff_alloc_fail';
13+
--error 5 #EE_OUTOFMEMORY
14+
delete d2 from t2 as d1, t1 as d2 where d1.a <=> d2.a;
15+
SET SESSION debug_dbug=DEFAULT;
16+
17+
drop table t2;
18+
drop table t1;

sql/uniques.cc

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
9797
max_elements= (ulong) (max_in_memory_size /
9898
ALIGN_SIZE(sizeof(TREE_ELEMENT)+size));
9999
(void) open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE,
100-
MYF(MY_WME));
100+
MYF(MY_WME));
101101
}
102102

103103

@@ -607,8 +607,10 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg)
607607
return 1;
608608
if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
609609
return 1;
610-
ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size;
611-
if (!(merge_buffer= (uchar *) my_malloc((ulong) buff_sz, MYF(0))))
610+
size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size;
611+
DBUG_EXECUTE_IF("make_merge_buff_alloc_fail",
612+
DBUG_SET("+d,simulate_out_of_memory"););
613+
if (!(merge_buffer = (uchar *)my_malloc(buff_sz, MYF(MY_WME))))
612614
return 1;
613615
if (buff_sz < (ulong) (full_size * (file_ptrs.elements + 1)))
614616
res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ;
@@ -737,9 +739,10 @@ bool Unique::get(TABLE *table)
737739
/* Not enough memory; Save the result to file && free memory used by tree */
738740
if (flush())
739741
return 1;
740-
741-
ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size;
742-
if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(0))))
742+
DBUG_EXECUTE_IF("make_merge_buff_alloc_fail",
743+
DBUG_SET("+d,simulate_out_of_memory"););
744+
size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size;
745+
if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(MY_WME))))
743746
return 1;
744747

745748
if (merge(table, sort_buffer, FALSE))

0 commit comments

Comments
 (0)