diff options
-rw-r--r-- | mysql-test/r/uniques_crash-7912.result | 18 | ||||
-rw-r--r-- | mysql-test/t/uniques_crash-7912.test | 18 | ||||
-rw-r--r-- | sql/uniques.cc | 15 |
3 files changed, 45 insertions, 6 deletions
diff --git a/mysql-test/r/uniques_crash-7912.result b/mysql-test/r/uniques_crash-7912.result new file mode 100644 index 00000000000..31029da5c86 --- /dev/null +++ b/mysql-test/r/uniques_crash-7912.result @@ -0,0 +1,18 @@ +set sql_mode=""; +drop table if exists t1,t2; +Warnings: +Note 1051 Unknown table 't1' +Note 1051 Unknown table 't2' +create table `t1` (`a` datetime not null) engine=InnoDB; +create table `t2` (`a` int not null) engine=innodb; +replace into t1 values (),(); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +insert into t2 values(0); +set session sort_buffer_size = 1024*1024*1024*1024; +SET session debug_dbug= '+d,make_merge_buff_alloc_fail'; +delete d2 from t2 as d1, t1 as d2 where d1.a <=> d2.a; +ERROR HY000: Out of memory (Needed 2 bytes) +SET SESSION debug_dbug=DEFAULT; +drop table t2; +drop table t1; diff --git a/mysql-test/t/uniques_crash-7912.test b/mysql-test/t/uniques_crash-7912.test new file mode 100644 index 00000000000..010855f7fb4 --- /dev/null +++ b/mysql-test/t/uniques_crash-7912.test @@ -0,0 +1,18 @@ +# MDEV-7912 +# multitable delete with wrongly set sort_buffer_size crashes in merge_buffers +--source include/have_innodb.inc +set sql_mode=""; +drop table if exists t1,t2; +create table `t1` (`a` datetime not null) engine=InnoDB; +create table `t2` (`a` int not null) engine=innodb; + +replace into t1 values (),(); +insert into t2 values(0); +set session sort_buffer_size = 1024*1024*1024*1024; +SET session debug_dbug= '+d,make_merge_buff_alloc_fail'; +--error 5 #EE_OUTOFMEMORY +delete d2 from t2 as d1, t1 as d2 where d1.a <=> d2.a; +SET SESSION debug_dbug=DEFAULT; + +drop table t2; +drop table t1;
\ No newline at end of file diff --git a/sql/uniques.cc b/sql/uniques.cc index 72411be5cd6..455fe205717 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -97,7 +97,7 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, max_elements= (ulong) (max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size)); (void) open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, - MYF(MY_WME)); + MYF(MY_WME)); } @@ -607,8 +607,10 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg) return 1; if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0)) return 1; - ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size; - if (!(merge_buffer= (uchar *) my_malloc((ulong) buff_sz, MYF(0)))) + size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size; + DBUG_EXECUTE_IF("make_merge_buff_alloc_fail", + DBUG_SET("+d,simulate_out_of_memory");); + if (!(merge_buffer = (uchar *)my_malloc(buff_sz, MYF(MY_WME)))) return 1; if (buff_sz < (ulong) (full_size * (file_ptrs.elements + 1))) res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ; @@ -737,9 +739,10 @@ bool Unique::get(TABLE *table) /* Not enough memory; Save the result to file && free memory used by tree */ if (flush()) return 1; - - ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size; - if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(0)))) + DBUG_EXECUTE_IF("make_merge_buff_alloc_fail", + DBUG_SET("+d,simulate_out_of_memory");); + size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size; + if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(MY_WME)))) return 1; if (merge(table, sort_buffer, FALSE)) |