Server crashes on SQL select containing more group by and left join statements using innodb tables

Resolves: #1065676
This commit is contained in:
Honza Horak 2014-03-12 11:38:27 +01:00
parent 1f0a46c2eb
commit 5b0ed2d410
2 changed files with 393 additions and 1 deletions

386
mariadb-rhbz1065676.patch Normal file
View File

@ -0,0 +1,386 @@
Backported from mariadb-5.5.37:
https://mariadb.atlassian.net/browse/MDEV-5724
https://bugzilla.redhat.com/show_bug.cgi?id=1065676
diff -up mariadb-5.5.36/mysql-test/r/stack-crash.result.rhbz1065676 mariadb-5.5.36/mysql-test/r/stack-crash.result
--- mariadb-5.5.36/mysql-test/r/stack-crash.result.rhbz1065676 2014-03-11 18:20:56.344327004 +0100
+++ mariadb-5.5.36/mysql-test/r/stack-crash.result 2014-03-11 18:20:56.344327004 +0100
@@ -0,0 +1,93 @@
+drop table if exists t1,t2;
+Warnings:
+Note 1051 Unknown table 't1'
+Note 1051 Unknown table 't2'
+CREATE TABLE t1 (
+`sspo_id` int(11) NOT NULL AUTO_INCREMENT,
+`sspo_uid` int(11) NOT NULL DEFAULT '0',
+`sspo_type` varchar(1) NOT NULL DEFAULT 'P',
+`sspo_text` longtext NOT NULL,
+`sspo_image` varchar(255) NOT NULL,
+`sspo_source` int(11) NOT NULL DEFAULT '0',
+`sspo_event_name` varchar(255) NOT NULL DEFAULT '',
+`sspo_event_location` varchar(255) NOT NULL DEFAULT '',
+`sspo_event_date` datetime DEFAULT NULL,
+`sspo_remote_title` varchar(255) NOT NULL,
+`sspo_remote_url` varchar(255) NOT NULL,
+`sspo_remote_desc` text NOT NULL,
+`sspo_remote_image` varchar(255) NOT NULL,
+`sspo_obj_status` varchar(1) NOT NULL DEFAULT 'A',
+`sspo_cr_date` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
+`sspo_cr_uid` int(11) NOT NULL DEFAULT '0',
+`sspo_lu_date` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
+`sspo_lu_uid` int(11) NOT NULL DEFAULT '0',
+PRIMARY KEY (`sspo_id`),
+KEY `post_uid` (`sspo_uid`,`sspo_cr_date`)
+) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
+Warnings:
+Warning 1286 Unknown storage engine 'InnoDB'
+Warning 1266 Using storage engine MyISAM for table 't1'
+INSERT INTO t1 VALUES (1,2,'P','test1','',0,'','',NULL,'','','','','A','2013-09-30 00:19:32',2,'2013-09-30 00:19:32',2),(2,2,'P','bbb','',0,'','',NULL,'','','','','A','2013-10-02 15:06:35',2,'2013-10-02 15:06:35',2);
+CREATE TABLE `t2` (
+`spoo_id` int(11) NOT NULL AUTO_INCREMENT,
+`spoo_user_type_id` int(11) NOT NULL DEFAULT '0',
+`spoo_uid` int(11) NOT NULL DEFAULT '0',
+`spoo_option_id` int(11) NOT NULL DEFAULT '0',
+`spoo_value` varchar(10000) NOT NULL,
+`spoo_obj_status` varchar(1) NOT NULL DEFAULT 'A',
+`spoo_cr_date` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
+`spoo_cr_uid` int(11) NOT NULL DEFAULT '0',
+`spoo_lu_date` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
+`spoo_lu_uid` int(11) NOT NULL DEFAULT '0',
+PRIMARY KEY (`spoo_id`),
+KEY `object_option_main_idx` (`spoo_user_type_id`,`spoo_uid`,`spoo_option_id`,`spoo_value`(255))
+) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8;
+Warnings:
+Warning 1286 Unknown storage engine 'InnoDB'
+Warning 1266 Using storage engine MyISAM for table 't2'
+INSERT INTO `t2` VALUES (19,1,2,6,'Dortmund','A','2013-09-26 01:36:51',2,'2013-09-26 01:36:51',2),(20,1,2,8,'49','A','2013-09-26 01:36:51',2,'2013-09-26 01:36:51',2);
+SELECT Count(*)
+FROM t1 AS tbl
+LEFT JOIN t2 a
+ON a.spoo_uid = sspo_uid
+AND a.spoo_option_id = 1
+LEFT JOIN t2 b
+ON b.spoo_uid = sspo_uid
+AND b.spoo_option_id = 2
+LEFT JOIN t2 c
+ON c.spoo_uid = sspo_uid
+AND c.spoo_option_id = 3
+LEFT JOIN t2 d
+ON d.spoo_uid = sspo_uid
+AND d.spoo_option_id = 5
+LEFT JOIN t2 e
+ON e.spoo_uid = sspo_uid
+AND e.spoo_option_id = 4
+LEFT JOIN t2 f
+ON f.spoo_uid = sspo_uid
+AND f.spoo_option_id = 11
+LEFT JOIN t2 g
+ON g.spoo_uid = sspo_uid
+AND g.spoo_option_id = 7
+LEFT JOIN t2 h
+ON h.spoo_uid = sspo_uid
+AND h.spoo_option_id = 10
+LEFT JOIN t2 i
+ON i.spoo_uid = sspo_uid
+AND i.spoo_option_id = 18
+LEFT JOIN t2 j
+ON j.spoo_uid = sspo_uid
+AND j.spoo_option_id = 6
+GROUP BY a.spoo_value,
+b.spoo_value,
+c.spoo_value,
+d.spoo_value,
+e.spoo_value,
+f.spoo_value,
+g.spoo_value,
+h.spoo_value,
+i.spoo_value,
+j.spoo_value;
+Count(*)
+2
+drop table t1,t2;
diff -up mariadb-5.5.36/mysql-test/t/stack-crash.test.rhbz1065676 mariadb-5.5.36/mysql-test/t/stack-crash.test
--- mariadb-5.5.36/mysql-test/t/stack-crash.test.rhbz1065676 2014-03-11 18:20:56.344327004 +0100
+++ mariadb-5.5.36/mysql-test/t/stack-crash.test 2014-03-11 18:20:56.344327004 +0100
@@ -0,0 +1,96 @@
+#
+# Test to ensure that we don't get stack overflows
+#
+
+drop table if exists t1,t2;
+
+#
+# MDEV-5724
+# Server crashes on SQL select containing more group by and left join
+# statements
+# This was because record_buffer was 300,000 bytes and caused stack overflow
+#
+
+CREATE TABLE t1 (
+ `sspo_id` int(11) NOT NULL AUTO_INCREMENT,
+ `sspo_uid` int(11) NOT NULL DEFAULT '0',
+ `sspo_type` varchar(1) NOT NULL DEFAULT 'P',
+ `sspo_text` longtext NOT NULL,
+ `sspo_image` varchar(255) NOT NULL,
+ `sspo_source` int(11) NOT NULL DEFAULT '0',
+ `sspo_event_name` varchar(255) NOT NULL DEFAULT '',
+ `sspo_event_location` varchar(255) NOT NULL DEFAULT '',
+ `sspo_event_date` datetime DEFAULT NULL,
+ `sspo_remote_title` varchar(255) NOT NULL,
+ `sspo_remote_url` varchar(255) NOT NULL,
+ `sspo_remote_desc` text NOT NULL,
+ `sspo_remote_image` varchar(255) NOT NULL,
+ `sspo_obj_status` varchar(1) NOT NULL DEFAULT 'A',
+ `sspo_cr_date` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
+ `sspo_cr_uid` int(11) NOT NULL DEFAULT '0',
+ `sspo_lu_date` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
+ `sspo_lu_uid` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`sspo_id`),
+ KEY `post_uid` (`sspo_uid`,`sspo_cr_date`)
+) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES (1,2,'P','test1','',0,'','',NULL,'','','','','A','2013-09-30 00:19:32',2,'2013-09-30 00:19:32',2),(2,2,'P','bbb','',0,'','',NULL,'','','','','A','2013-10-02 15:06:35',2,'2013-10-02 15:06:35',2);
+
+CREATE TABLE `t2` (
+ `spoo_id` int(11) NOT NULL AUTO_INCREMENT,
+ `spoo_user_type_id` int(11) NOT NULL DEFAULT '0',
+ `spoo_uid` int(11) NOT NULL DEFAULT '0',
+ `spoo_option_id` int(11) NOT NULL DEFAULT '0',
+ `spoo_value` varchar(10000) NOT NULL,
+ `spoo_obj_status` varchar(1) NOT NULL DEFAULT 'A',
+ `spoo_cr_date` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
+ `spoo_cr_uid` int(11) NOT NULL DEFAULT '0',
+ `spoo_lu_date` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
+ `spoo_lu_uid` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`spoo_id`),
+ KEY `object_option_main_idx` (`spoo_user_type_id`,`spoo_uid`,`spoo_option_id`,`spoo_value`(255))
+) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8;
+INSERT INTO `t2` VALUES (19,1,2,6,'Dortmund','A','2013-09-26 01:36:51',2,'2013-09-26 01:36:51',2),(20,1,2,8,'49','A','2013-09-26 01:36:51',2,'2013-09-26 01:36:51',2);
+
+SELECT Count(*)
+FROM t1 AS tbl
+ LEFT JOIN t2 a
+ ON a.spoo_uid = sspo_uid
+ AND a.spoo_option_id = 1
+ LEFT JOIN t2 b
+ ON b.spoo_uid = sspo_uid
+ AND b.spoo_option_id = 2
+ LEFT JOIN t2 c
+ ON c.spoo_uid = sspo_uid
+ AND c.spoo_option_id = 3
+ LEFT JOIN t2 d
+ ON d.spoo_uid = sspo_uid
+ AND d.spoo_option_id = 5
+ LEFT JOIN t2 e
+ ON e.spoo_uid = sspo_uid
+ AND e.spoo_option_id = 4
+ LEFT JOIN t2 f
+ ON f.spoo_uid = sspo_uid
+ AND f.spoo_option_id = 11
+ LEFT JOIN t2 g
+ ON g.spoo_uid = sspo_uid
+ AND g.spoo_option_id = 7
+ LEFT JOIN t2 h
+ ON h.spoo_uid = sspo_uid
+ AND h.spoo_option_id = 10
+ LEFT JOIN t2 i
+ ON i.spoo_uid = sspo_uid
+ AND i.spoo_option_id = 18
+ LEFT JOIN t2 j
+ ON j.spoo_uid = sspo_uid
+ AND j.spoo_option_id = 6
+GROUP BY a.spoo_value,
+ b.spoo_value,
+ c.spoo_value,
+ d.spoo_value,
+ e.spoo_value,
+ f.spoo_value,
+ g.spoo_value,
+ h.spoo_value,
+ i.spoo_value,
+ j.spoo_value;
+drop table t1,t2;
diff -up mariadb-5.5.36/storage/maria/ma_blockrec.c.rhbz1065676 mariadb-5.5.36/storage/maria/ma_blockrec.c
--- mariadb-5.5.36/storage/maria/ma_blockrec.c.rhbz1065676 2014-02-24 00:50:19.000000000 +0100
+++ mariadb-5.5.36/storage/maria/ma_blockrec.c 2014-03-11 18:20:56.347327004 +0100
@@ -5144,7 +5144,12 @@ my_bool _ma_cmp_block_unique(MARIA_HA *i
int error;
DBUG_ENTER("_ma_cmp_block_unique");
- if (!(old_record= my_alloca(info->s->base.reclength)))
+ /*
+ Don't allocate more than 16K on the stack to ensure we don't get
+ stack overflow.
+ */
+ if (!(old_record= my_safe_alloca(info->s->base.reclength,
+ MARIA_MAX_RECORD_ON_STACK)))
DBUG_RETURN(1);
/* Don't let the compare destroy blobs that may be in use */
@@ -5166,7 +5171,8 @@ my_bool _ma_cmp_block_unique(MARIA_HA *i
info->rec_buff_size= org_rec_buff_size;
}
DBUG_PRINT("exit", ("result: %d", error));
- my_afree(old_record);
+ my_safe_afree(old_record, info->s->base.reclength,
+ MARIA_MAX_RECORD_ON_STACK);
DBUG_RETURN(error != 0);
}
diff -up mariadb-5.5.36/storage/maria/ma_dynrec.c.rhbz1065676 mariadb-5.5.36/storage/maria/ma_dynrec.c
--- mariadb-5.5.36/storage/maria/ma_dynrec.c.rhbz1065676 2014-02-24 00:50:16.000000000 +0100
+++ mariadb-5.5.36/storage/maria/ma_dynrec.c 2014-03-11 18:20:56.348327004 +0100
@@ -36,12 +36,6 @@ static my_bool delete_dynamic_record(MAR
static my_bool _ma_cmp_buffer(File file, const uchar *buff, my_off_t filepos,
uint length);
-/* Play it safe; We have a small stack when using threads */
-#undef my_alloca
-#undef my_afree
-#define my_alloca(A) my_malloc((A),MYF(0))
-#define my_afree(A) my_free((A))
-
/* Interface function from MARIA_HA */
#ifdef HAVE_MMAP
@@ -256,7 +250,8 @@ my_bool _ma_write_blob_record(MARIA_HA *
MARIA_DYN_DELETE_BLOCK_HEADER+1);
reclength= (info->s->base.pack_reclength +
_ma_calc_total_blob_length(info,record)+ extra);
- if (!(rec_buff=(uchar*) my_alloca(reclength)))
+ if (!(rec_buff=(uchar*) my_safe_alloca(reclength,
+ MARIA_MAX_RECORD_ON_STACK)))
{
my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
return(1);
@@ -270,7 +265,7 @@ my_bool _ma_write_blob_record(MARIA_HA *
error= write_dynamic_record(info,
rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
reclength2);
- my_afree(rec_buff);
+ my_safe_afree(rec_buff, reclength, MARIA_MAX_RECORD_ON_STACK);
return(error != 0);
}
@@ -294,7 +289,8 @@ my_bool _ma_update_blob_record(MARIA_HA
return 1;
}
#endif
- if (!(rec_buff=(uchar*) my_alloca(reclength)))
+ if (!(rec_buff=(uchar*) my_safe_alloca(reclength,
+ MARIA_MAX_RECORD_ON_STACK)))
{
my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
return(1);
@@ -304,7 +300,7 @@ my_bool _ma_update_blob_record(MARIA_HA
error=update_dynamic_record(info,pos,
rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
reclength);
- my_afree(rec_buff);
+ my_safe_afree(rec_buff, reclength, MARIA_MAX_RECORD_ON_STACK);
return(error != 0);
}
@@ -1559,7 +1555,8 @@ my_bool _ma_cmp_dynamic_unique(MARIA_HA
my_bool error;
DBUG_ENTER("_ma_cmp_dynamic_unique");
- if (!(old_record=my_alloca(info->s->base.reclength)))
+ if (!(old_record= my_safe_alloca(info->s->base.reclength,
+ MARIA_MAX_RECORD_ON_STACK)))
DBUG_RETURN(1);
/* Don't let the compare destroy blobs that may be in use */
@@ -1580,7 +1577,8 @@ my_bool _ma_cmp_dynamic_unique(MARIA_HA
info->rec_buff= old_rec_buff;
info->rec_buff_size= old_rec_buff_size;
}
- my_afree(old_record);
+ my_safe_afree(old_record, info->s->base.reclength,
+ MARIA_MAX_RECORD_ON_STACK);
DBUG_RETURN(error);
}
@@ -1595,6 +1593,9 @@ my_bool _ma_cmp_dynamic_record(register
uchar *buffer;
MARIA_BLOCK_INFO block_info;
my_bool error= 1;
+ size_t buffer_length;
+ LINT_INIT(buffer_length);
+
DBUG_ENTER("_ma_cmp_dynamic_record");
if (info->opt_flag & WRITE_CACHE_USED)
@@ -1612,8 +1613,10 @@ my_bool _ma_cmp_dynamic_record(register
{ /* If check isn't disabled */
if (info->s->base.blobs)
{
- if (!(buffer=(uchar*) my_alloca(info->s->base.pack_reclength+
- _ma_calc_total_blob_length(info,record))))
+ buffer_length= (info->s->base.pack_reclength +
+ _ma_calc_total_blob_length(info,record));
+ if (!(buffer=(uchar*) my_safe_alloca(buffer_length,
+ MARIA_MAX_RECORD_ON_STACK)))
DBUG_RETURN(1);
}
reclength= _ma_rec_pack(info,buffer,record);
@@ -1665,7 +1668,7 @@ my_bool _ma_cmp_dynamic_record(register
error= 0;
err:
if (buffer != info->rec_buff)
- my_afree(buffer);
+ my_safe_afree(buffer, buffer_length, MARIA_MAX_RECORD_ON_STACK);
DBUG_PRINT("exit", ("result: %d", error));
DBUG_RETURN(error);
}
diff -up mariadb-5.5.36/storage/maria/maria_def.h.rhbz1065676 mariadb-5.5.36/storage/maria/maria_def.h
--- mariadb-5.5.36/storage/maria/maria_def.h.rhbz1065676 2014-02-24 00:50:21.000000000 +0100
+++ mariadb-5.5.36/storage/maria/maria_def.h 2014-03-11 18:20:56.348327004 +0100
@@ -42,6 +42,7 @@
#define MAX_NONMAPPED_INSERTS 1000
#define MARIA_MAX_TREE_LEVELS 32
+#define MARIA_MAX_RECORD_ON_STACK 16384
/* maria_open() flag, specific for maria_pack */
#define HA_OPEN_IGNORE_MOVED_STATE (1U << 30)
diff -up mariadb-5.5.36/storage/maria/maria_pack.c.rhbz1065676 mariadb-5.5.36/storage/maria/maria_pack.c
--- mariadb-5.5.36/storage/maria/maria_pack.c.rhbz1065676 2014-02-24 00:50:16.000000000 +0100
+++ mariadb-5.5.36/storage/maria/maria_pack.c 2014-03-11 18:20:56.351327005 +0100
@@ -861,7 +861,7 @@ static int get_statistic(PACK_MRG_INFO *
reclength= mrg->file[0]->s->base.reclength;
null_bytes= mrg->file[0]->s->base.null_bytes;
- record=(uchar*) my_alloca(reclength);
+ record=(uchar*) my_safe_alloca(reclength, MARIA_MAX_RECORD_ON_STACK);
end_count=huff_counts+mrg->file[0]->s->base.fields;
record_count=0; glob_crc=0;
max_blob_length=0;
@@ -1145,7 +1145,7 @@ static int get_statistic(PACK_MRG_INFO *
mrg->records=record_count;
mrg->max_blob_length=max_blob_length;
- my_afree(record);
+ my_safe_afree(record, reclength, MARIA_MAX_RECORD_ON_STACK);
DBUG_RETURN(error != HA_ERR_END_OF_FILE);
}
@@ -2415,7 +2415,8 @@ static int compress_maria_file(PACK_MRG_
DBUG_ENTER("compress_maria_file");
/* Allocate a buffer for the records (excluding blobs). */
- if (!(record=(uchar*) my_alloca(isam_file->s->base.reclength)))
+ if (!(record=(uchar*) my_safe_alloca(isam_file->s->base.reclength,
+ MARIA_MAX_RECORD_ON_STACK)))
return -1;
end_count=huff_counts+isam_file->s->base.fields;
@@ -2778,7 +2779,8 @@ static int compress_maria_file(PACK_MRG_
if (verbose >= 2)
printf("wrote %s records.\n", llstr((longlong) record_count, llbuf));
- my_afree(record);
+ my_safe_afree(record, isam_file->s->base.reclength,
+ MARIA_MAX_RECORD_ON_STACK);
mrg->ref_length=max_pack_length;
mrg->min_pack_length=max_record_length ? min_record_length : 0;
mrg->max_pack_length=max_record_length;

View File

@ -7,7 +7,7 @@
Name: mariadb
Version: 5.5.36
Release: 1%{?dist}
Release: 2%{?dist}
Epoch: 1
Summary: A community developed branch of MySQL
@ -69,6 +69,7 @@ Patch17: mariadb-covscan-signexpr.patch
Patch18: mariadb-covscan-stroverflow.patch
Patch19: mariadb-config.patch
Patch20: mariadb-ssltest.patch
Patch21: mariadb-rhbz1065676.patch
BuildRequires: perl, readline-devel, openssl-devel
BuildRequires: cmake, ncurses-devel, zlib-devel, libaio-devel
@ -269,6 +270,7 @@ MariaDB is a community developed branch of MySQL.
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
# workaround for upstream bug #56342
rm -f mysql-test/t/ssl_8k_key-master.opt
@ -804,6 +806,10 @@ fi
%{_mandir}/man1/mysql_client_test.1*
%changelog
* Wed Mar 12 2014 Honza Horak <hhorak@redhat.com> - 1:5.5.36-2
- Server crashes on SQL select containing more group by and left join statements using innodb tables
Resolves: #1065676
* Thu Mar 06 2014 Honza Horak <hhorak@redhat.com> - 1:5.5.36-1
- Rebase to 5.5.36
https://kb.askmonty.org/en/mariadb-5536-changelog/