Commit 4e7f3fb8 authored by Vlad Lesin's avatar Vlad Lesin

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.
parent 90e7e678
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;
--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;
...@@ -782,27 +782,29 @@ static HUFF_COUNTS *init_huff_count(MARIA_HA *info,my_off_t records) ...@@ -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++) for (i=0 ; i < info->s->base.fields ; i++)
{ {
enum en_fieldtype type; enum en_fieldtype type;
count[i].field_length=info->s->columndef[i].length; uint col_nr = info->s->columndef[i].column_nr;
type= count[i].field_type= (enum en_fieldtype) info->s->columndef[i].type; 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 || if (type == FIELD_INTERVALL ||
type == FIELD_CONSTANT || type == FIELD_CONSTANT ||
type == FIELD_ZERO) type == FIELD_ZERO)
type = FIELD_NORMAL; type = FIELD_NORMAL;
if (count[i].field_length <= 8 && if (count[col_nr].field_length <= 8 &&
(type == FIELD_NORMAL || (type == FIELD_NORMAL ||
type == FIELD_SKIP_ZERO)) 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 For every column initialize a tree, which is used to detect distinct
column values. 'int_tree' works together with 'tree_buff' and column values. 'int_tree' works together with 'tree_buff' and
'tree_pos'. It's keys are implemented by pointers into 'tree_buff'. 'tree_pos'. It's keys are implemented by pointers into 'tree_buff'.
This is accomplished by '-1' as the element size. 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)); NULL, MYF(0));
if (records && type != FIELD_BLOB && type != FIELD_VARCHAR) if (records && type != FIELD_BLOB && type != FIELD_VARCHAR)
count[i].tree_pos=count[i].tree_buff = count[col_nr].tree_pos=count[col_nr].tree_buff =
my_malloc(count[i].field_length > 1 ? tree_buff_length : 2, my_malloc(count[col_nr].field_length > 1 ? tree_buff_length : 2,
MYF(MY_WME)); MYF(MY_WME));
} }
} }
......
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