Skip to content

Commit 38cad68

Browse files
author
Varun Gupta
committed
MDEV-18899: Server crashes in Field::set_warning_truncated_wrong_value
To fix the crash there we need to make sure that the server while storing the statistical values in statistical tables should do it in a multi-byte safe way. Also there is no need to throw warnings if there is truncation while storing values from statistical fields.
1 parent 1e9c2b2 commit 38cad68

File tree

5 files changed

+166
-5
lines changed

5 files changed

+166
-5
lines changed

mysql-test/r/stat_tables.result

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,4 +624,61 @@ SELECT MAX(pk) FROM t1;
624624
MAX(pk)
625625
NULL
626626
DROP TABLE t1;
627+
#
628+
# MDEV-18899: Server crashes in Field::set_warning_truncated_wrong_value
629+
#
630+
set names utf8;
631+
set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
632+
set optimizer_use_condition_selectivity=4;
633+
set use_stat_tables=preferably;
634+
set @save_histogram_size= @@histogram_size;
635+
set histogram_size=255;
636+
create table t1 ( a varchar(255) character set utf8);
637+
insert into t1 values (REPEAT('ӥ',255)), (REPEAT('ç',255));
638+
analyze table t1;
639+
Table Op Msg_type Msg_text
640+
test.t1 analyze status Engine-independent statistics collected
641+
test.t1 analyze status OK
642+
select HEX(RIGHT(min_value, 1)), length(min_value) from mysql.column_stats where db_name='test' and table_name='t1';
643+
HEX(RIGHT(min_value, 1)) length(min_value)
644+
A7 254
645+
select HEX(RIGHT(max_value, 1)), length(max_value) from mysql.column_stats where db_name='test' and table_name='t1';
646+
HEX(RIGHT(max_value, 1)) length(max_value)
647+
A5 254
648+
analyze select * from t1 where a >= 'ӥ';
649+
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
650+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 2.00 50.00 50.00 Using where
651+
set @save_sql_mode= @@sql_mode;
652+
set sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
653+
update mysql.column_stats set min_value= REPEAT('ӥ',255) where db_name='test' and table_name='t1';
654+
Warnings:
655+
Warning 1265 Data truncated for column 'min_value' at row 1
656+
select HEX(RIGHT(min_value, 1)), length(min_value) from mysql.column_stats where db_name='test' and table_name='t1';
657+
HEX(RIGHT(min_value, 1)) length(min_value)
658+
D3 255
659+
analyze select * from t1 where a >= 'ӥ';
660+
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
661+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 2.00 50.00 50.00 Using where
662+
set names latin1;
663+
drop table t1;
664+
CREATE TABLE t1 (col1 date);
665+
INSERT INTO t1 VALUES('2004-01-01'),('2004-02-29');
666+
INSERT INTO t1 VALUES('0000-10-31');
667+
analyze table t1;
668+
Table Op Msg_type Msg_text
669+
test.t1 analyze status Engine-independent statistics collected
670+
test.t1 analyze status OK
671+
update mysql.column_stats set min_value='2004-0-31123' where db_name='test' and table_name='t1';
672+
select min_value from mysql.column_stats where db_name='test' and table_name='t1';
673+
min_value
674+
2004-0-31123
675+
select * from t1;
676+
col1
677+
2004-01-01
678+
2004-02-29
679+
0000-10-31
680+
drop table t1;
681+
set @@sql_mode= @save_sql_mode;
627682
set use_stat_tables=@save_use_stat_tables;
683+
set @@histogram_size= @save_histogram_size;
684+
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;

mysql-test/r/stat_tables_innodb.result

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,63 @@ SELECT MAX(pk) FROM t1;
651651
MAX(pk)
652652
NULL
653653
DROP TABLE t1;
654+
#
655+
# MDEV-18899: Server crashes in Field::set_warning_truncated_wrong_value
656+
#
657+
set names utf8;
658+
set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
659+
set optimizer_use_condition_selectivity=4;
660+
set use_stat_tables=preferably;
661+
set @save_histogram_size= @@histogram_size;
662+
set histogram_size=255;
663+
create table t1 ( a varchar(255) character set utf8);
664+
insert into t1 values (REPEAT('ӥ',255)), (REPEAT('ç',255));
665+
analyze table t1;
666+
Table Op Msg_type Msg_text
667+
test.t1 analyze status Engine-independent statistics collected
668+
test.t1 analyze status OK
669+
select HEX(RIGHT(min_value, 1)), length(min_value) from mysql.column_stats where db_name='test' and table_name='t1';
670+
HEX(RIGHT(min_value, 1)) length(min_value)
671+
A7 254
672+
select HEX(RIGHT(max_value, 1)), length(max_value) from mysql.column_stats where db_name='test' and table_name='t1';
673+
HEX(RIGHT(max_value, 1)) length(max_value)
674+
A5 254
675+
analyze select * from t1 where a >= 'ӥ';
676+
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
677+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 2.00 50.00 50.00 Using where
678+
set @save_sql_mode= @@sql_mode;
679+
set sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
680+
update mysql.column_stats set min_value= REPEAT('ӥ',255) where db_name='test' and table_name='t1';
681+
Warnings:
682+
Warning 1265 Data truncated for column 'min_value' at row 1
683+
select HEX(RIGHT(min_value, 1)), length(min_value) from mysql.column_stats where db_name='test' and table_name='t1';
684+
HEX(RIGHT(min_value, 1)) length(min_value)
685+
D3 255
686+
analyze select * from t1 where a >= 'ӥ';
687+
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
688+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 2.00 50.00 50.00 Using where
689+
set names latin1;
690+
drop table t1;
691+
CREATE TABLE t1 (col1 date);
692+
INSERT INTO t1 VALUES('2004-01-01'),('2004-02-29');
693+
INSERT INTO t1 VALUES('0000-10-31');
694+
analyze table t1;
695+
Table Op Msg_type Msg_text
696+
test.t1 analyze status Engine-independent statistics collected
697+
test.t1 analyze status OK
698+
update mysql.column_stats set min_value='2004-0-31123' where db_name='test' and table_name='t1';
699+
select min_value from mysql.column_stats where db_name='test' and table_name='t1';
700+
min_value
701+
2004-0-31123
702+
select * from t1;
703+
col1
704+
2004-01-01
705+
2004-02-29
706+
0000-10-31
707+
drop table t1;
708+
set @@sql_mode= @save_sql_mode;
654709
set use_stat_tables=@save_use_stat_tables;
710+
set @@histogram_size= @save_histogram_size;
711+
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
655712
set optimizer_switch=@save_optimizer_switch_for_stat_tables_test;
656713
SET SESSION STORAGE_ENGINE=DEFAULT;

mysql-test/t/stat_tables.test

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,4 +401,44 @@ SELECT MAX(pk) FROM t1;
401401

402402
DROP TABLE t1;
403403

404+
--echo #
405+
--echo # MDEV-18899: Server crashes in Field::set_warning_truncated_wrong_value
406+
--echo #
407+
408+
set names utf8;
409+
set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
410+
set optimizer_use_condition_selectivity=4;
411+
set use_stat_tables=preferably;
412+
set @save_histogram_size= @@histogram_size;
413+
set histogram_size=255;
414+
415+
create table t1 ( a varchar(255) character set utf8);
416+
insert into t1 values (REPEAT('ӥ',255)), (REPEAT('ç',255));
417+
418+
analyze table t1;
419+
select HEX(RIGHT(min_value, 1)), length(min_value) from mysql.column_stats where db_name='test' and table_name='t1';
420+
select HEX(RIGHT(max_value, 1)), length(max_value) from mysql.column_stats where db_name='test' and table_name='t1';
421+
analyze select * from t1 where a >= 'ӥ';
422+
423+
set @save_sql_mode= @@sql_mode;
424+
set sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
425+
update mysql.column_stats set min_value= REPEAT('ӥ',255) where db_name='test' and table_name='t1';
426+
select HEX(RIGHT(min_value, 1)), length(min_value) from mysql.column_stats where db_name='test' and table_name='t1';
427+
analyze select * from t1 where a >= 'ӥ';
428+
429+
set names latin1;
430+
drop table t1;
431+
432+
CREATE TABLE t1 (col1 date);
433+
INSERT INTO t1 VALUES('2004-01-01'),('2004-02-29');
434+
INSERT INTO t1 VALUES('0000-10-31');
435+
analyze table t1;
436+
update mysql.column_stats set min_value='2004-0-31123' where db_name='test' and table_name='t1';
437+
select min_value from mysql.column_stats where db_name='test' and table_name='t1';
438+
select * from t1;
439+
drop table t1;
440+
441+
set @@sql_mode= @save_sql_mode;
404442
set use_stat_tables=@save_use_stat_tables;
443+
set @@histogram_size= @save_histogram_size;
444+
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;

sql/field.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7027,8 +7027,11 @@ Field_longstr::check_string_copy_error(const String_copier *copier,
70277027
if (!(pos= copier->most_important_error_pos()))
70287028
return FALSE;
70297029

7030-
convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6);
7031-
set_warning_truncated_wrong_value("string", tmp);
7030+
if (!is_stat_field)
7031+
{
7032+
convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6);
7033+
set_warning_truncated_wrong_value("string", tmp);
7034+
}
70327035
return TRUE;
70337036
}
70347037

sql/sql_statistics.cc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,9 @@ class Column_stat: public Stat_table
10601060
else
10611061
{
10621062
table_field->collected_stats->min_value->val_str(&val);
1063-
stat_field->store(val.ptr(), val.length(), &my_charset_bin);
1063+
uint32 length= Well_formed_prefix(val.charset(), val.ptr(),
1064+
MY_MIN(val.length(), stat_field->field_length)).length();
1065+
stat_field->store(val.ptr(), length, &my_charset_bin);
10641066
}
10651067
break;
10661068
case COLUMN_STAT_MAX_VALUE:
@@ -1069,7 +1071,9 @@ class Column_stat: public Stat_table
10691071
else
10701072
{
10711073
table_field->collected_stats->max_value->val_str(&val);
1072-
stat_field->store(val.ptr(), val.length(), &my_charset_bin);
1074+
uint32 length= Well_formed_prefix(val.charset(), val.ptr(),
1075+
MY_MIN(val.length(), stat_field->field_length)).length();
1076+
stat_field->store(val.ptr(), length, &my_charset_bin);
10731077
}
10741078
break;
10751079
case COLUMN_STAT_NULLS_RATIO:
@@ -3059,7 +3063,7 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
30593063
}
30603064
}
30613065
}
3062-
3066+
30633067
table->stats_is_read= TRUE;
30643068

30653069
DBUG_RETURN(0);

0 commit comments

Comments
 (0)