summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVlad Lesin <vlad_lesin@mail.ru>2020-01-20 22:56:01 +0300
committerVlad Lesin <vlad_lesin@mail.ru>2020-01-21 17:06:31 +0300
commit4e7f3fb8332c42c3beb2376ee0d90f559f1e7470 (patch)
tree5a5a29224bbff1370db58b11fac9b61a26aac1b5
parent90e7e6783b8a667012146e16f4d804a0c8b9ee8a (diff)
downloadmariadb-git-4e7f3fb8332c42c3beb2376ee0d90f559f1e7470.tar.gz
MDEV-14183: aria_pack segfaults in compress_maria_file
Column definition order in st_maria_share::columndef can differ from order of fields in record(see also st_maria_share::column_nr, st_maria_columndef::column_nr, _ma_column_nr_write(), _ma_column_nr_read()). This was not taken into account in aria_pack tool. The fix is to initialize elements of HUFF_COUNTS array in the correct order.
-rw-r--r--mysql-test/suite/maria/aria_pack_mdev14183.result22
-rw-r--r--mysql-test/suite/maria/aria_pack_mdev14183.test22
-rw-r--r--storage/maria/maria_pack.c16
3 files changed, 53 insertions, 7 deletions
diff --git a/mysql-test/suite/maria/aria_pack_mdev14183.result b/mysql-test/suite/maria/aria_pack_mdev14183.result
new file mode 100644
index 00000000000..cd1decdef75
--- /dev/null
+++ b/mysql-test/suite/maria/aria_pack_mdev14183.result
@@ -0,0 +1,22 @@
+CREATE TABLE `t` (
+`col_1` varchar(255) NOT NULL DEFAULT '',
+`col_2` varchar(255) NOT NULL,
+`col_3` int(11) NOT NULL DEFAULT '0',
+`col_4` int(11) NOT NULL DEFAULT '0'
+) ENGINE=Aria;
+insert into t values
+('foobar','qux',0,0),('abcdef','qux',0,0);
+Compressing test/t.MAD: (2 records)
+- Calculating statistics
+
+normal: 0 empty-space: 0 empty-zero: 0 empty-fill: 0
+pre-space: 0 end-space: 0 intervall-fields: 0 zero: 2
+Original trees: 4 After join: 1
+- Compressing file
+Min record length: 5 Max length: 5 Mean total length: 35
+99.57%
+SELECT * FROM t;
+col_1 col_2 col_3 col_4
+foobar qux 0 0
+abcdef qux 0 0
+DROP TABLE t;
diff --git a/mysql-test/suite/maria/aria_pack_mdev14183.test b/mysql-test/suite/maria/aria_pack_mdev14183.test
new file mode 100644
index 00000000000..ab0589dc780
--- /dev/null
+++ b/mysql-test/suite/maria/aria_pack_mdev14183.test
@@ -0,0 +1,22 @@
+--source include/have_aria.inc
+--source include/have_debug.inc
+
+CREATE TABLE `t` (
+ `col_1` varchar(255) NOT NULL DEFAULT '',
+ `col_2` varchar(255) NOT NULL,
+ `col_3` int(11) NOT NULL DEFAULT '0',
+ `col_4` int(11) NOT NULL DEFAULT '0'
+) ENGINE=Aria;
+
+insert into t values
+ ('foobar','qux',0,0),('abcdef','qux',0,0);
+
+--let $datadir= `SELECT @@datadir`
+--source include/shutdown_mysqld.inc
+# maria_pack crashes by assert() if the bug is not fixed
+--exec cd $datadir && $MARIA_PACK -t test/t
+
+--source include/start_mysqld.inc
+SELECT * FROM t;
+
+DROP TABLE t;
diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c
index 5166ae63758..6f2d9fe8a5d 100644
--- a/storage/maria/maria_pack.c
+++ b/storage/maria/maria_pack.c
@@ -782,27 +782,29 @@ static HUFF_COUNTS *init_huff_count(MARIA_HA *info,my_off_t records)
for (i=0 ; i < info->s->base.fields ; i++)
{
enum en_fieldtype type;
- count[i].field_length=info->s->columndef[i].length;
- type= count[i].field_type= (enum en_fieldtype) info->s->columndef[i].type;
+ uint col_nr = info->s->columndef[i].column_nr;
+ count[col_nr].field_length=info->s->columndef[i].length;
+ type= count[col_nr].field_type=
+ (enum en_fieldtype) info->s->columndef[i].type;
if (type == FIELD_INTERVALL ||
type == FIELD_CONSTANT ||
type == FIELD_ZERO)
type = FIELD_NORMAL;
- if (count[i].field_length <= 8 &&
+ if (count[col_nr].field_length <= 8 &&
(type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO))
- count[i].max_zero_fill= count[i].field_length;
+ count[col_nr].max_zero_fill= count[col_nr].field_length;
/*
For every column initialize a tree, which is used to detect distinct
column values. 'int_tree' works together with 'tree_buff' and
'tree_pos'. It's keys are implemented by pointers into 'tree_buff'.
This is accomplished by '-1' as the element size.
*/
- init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree, NULL,
+ init_tree(&count[col_nr].int_tree,0,0,-1,(qsort_cmp2) compare_tree, NULL,
NULL, MYF(0));
if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
- count[i].tree_pos=count[i].tree_buff =
- my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
+ count[col_nr].tree_pos=count[col_nr].tree_buff =
+ my_malloc(count[col_nr].field_length > 1 ? tree_buff_length : 2,
MYF(MY_WME));
}
}