diff --git a/mysql-test/main/ctype_filename.result b/mysql-test/main/ctype_filename.result index 0b214d394da..cf7d7118eb7 100644 --- a/mysql-test/main/ctype_filename.result +++ b/mysql-test/main/ctype_filename.result @@ -160,3 +160,18 @@ ALTER TABLE t1 CONVERT TO CHARACTER SET filename; ERROR 42000: Column length too big for column 'a' (max = 204); use BLOB or TEXT instead DROP TABLE t1; # End of 10.5 tests +# +# Start of 10.6 tests +# +# +# MDEV-35393 ASAN unknown-crash in Field_varstring::reset when inserting NULL value to a table with filename charset +# +SET sql_mode=''; +CREATE TABLE t (a CHAR(205)) ENGINE=MYISAM CHARACTER SET filename; +Warnings: +Note 1246 Converting column 'a' from CHAR to VARCHAR +INSERT INTO t VALUES (NULL); +DROP TABLE t; +# +# End of 10.6 tests +# diff --git a/mysql-test/main/ctype_filename.test b/mysql-test/main/ctype_filename.test index 83d1a7a5d5b..08e7269e0d3 100644 --- a/mysql-test/main/ctype_filename.test +++ b/mysql-test/main/ctype_filename.test @@ -167,3 +167,21 @@ ALTER TABLE t1 CONVERT TO CHARACTER SET filename; DROP TABLE t1; --echo # End of 10.5 tests + + +--echo # +--echo # Start of 10.6 tests +--echo # + +--echo # +--echo # MDEV-35393 ASAN unknown-crash in Field_varstring::reset when inserting NULL value to a table with filename charset +--echo # + +SET sql_mode=''; +CREATE TABLE t (a CHAR(205)) ENGINE=MYISAM CHARACTER SET filename; +INSERT INTO t VALUES (NULL); +DROP TABLE t; + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/mysql-test/main/ctype_filename_innodb.result b/mysql-test/main/ctype_filename_innodb.result new file mode 100644 index 00000000000..d3535e70a3f --- /dev/null +++ b/mysql-test/main/ctype_filename_innodb.result @@ -0,0 +1,18 @@ +# +# Start of 10.6 tests +# +# +# MDEV-35392 Assertion `!__asan_region_is_poisoned((vo id*) dest,templ->mysql_col_len)' failed in void row_sel_field_store_in_mysql_format_func(byte *, const mysql_row_templ_t *, const byte *, ulint) +# +SET sql_mode=''; +CREATE TABLE t (a CHAR(205)) ENGINE=INNODB CHARACTER SET filename; +Warnings: +Note 1246 Converting column 'a' from CHAR to VARCHAR +INSERT INTO t VALUES (1); +SELECT * FROM t; +a +1 +DROP TABLE t; +# +# End of 10.6 tests +# diff --git a/mysql-test/main/ctype_filename_innodb.test b/mysql-test/main/ctype_filename_innodb.test new file mode 100644 index 00000000000..a0340919c04 --- /dev/null +++ b/mysql-test/main/ctype_filename_innodb.test @@ -0,0 +1,19 @@ +--source include/have_innodb.inc + +--echo # +--echo # Start of 10.6 tests +--echo # + +--echo # +--echo # MDEV-35392 Assertion `!__asan_region_is_poisoned((vo id*) dest,templ->mysql_col_len)' failed in void row_sel_field_store_in_mysql_format_func(byte *, const mysql_row_templ_t *, const byte *, ulint) +--echo # + +SET sql_mode=''; +CREATE TABLE t (a CHAR(205)) ENGINE=INNODB CHARACTER SET filename; +INSERT INTO t VALUES (1); +SELECT * FROM t; +DROP TABLE t; + +--echo # +--echo # End of 10.6 tests +--echo # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 45f737812e4..654fc2e93be 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2307,6 +2307,34 @@ bool Column_definition::prepare_stage1_string(THD *thd, handler *file, ulonglong table_flags) { + if (real_field_type() == FIELD_TYPE_STRING && + length*charset->mbmaxlen > 1024) + { + DBUG_ASSERT(charset->mbmaxlen > 4); + /* + Convert long CHAR columns to VARCHAR. + CHAR has an octet length limit of 1024 bytes. + The code in Binlog_type_info_fixed_string::Binlog_type_info_fixed_string + relies on this limit. If octet length of a CHAR column is greater + than 1024, then it cannot write its metadata to binlog properly. + In case of the filename character set with mbmaxlen=5, + the maximum possible character length is 1024/5=204 characters. + Upgrade to VARCHAR if octet length is greater than 1024. + */ + char warn_buff[MYSQL_ERRMSG_SIZE]; + if (thd->is_strict_mode()) + { + my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str, + static_cast(1024 / charset->mbmaxlen)); + return true; + } + set_handler(&type_handler_varchar); + my_snprintf(warn_buff, sizeof(warn_buff), ER_THD(thd, ER_AUTO_CONVERT), + field_name.str, "CHAR", "VARCHAR"); + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_AUTO_CONVERT, + warn_buff); + } + create_length_to_internal_length_string(); if (prepare_blob_field(thd)) return true; @@ -3779,33 +3807,6 @@ bool Column_definition::prepare_blob_field(THD *thd) { DBUG_ENTER("Column_definition::prepare_blob_field"); - if (real_field_type() == FIELD_TYPE_STRING && length > 1024) - { - DBUG_ASSERT(charset->mbmaxlen > 4); - /* - Convert long CHAR columns to VARCHAR. - CHAR has an octet length limit of 1024 bytes. - The code in Binlog_type_info_fixed_string::Binlog_type_info_fixed_string - relies on this limit. If octet length of a CHAR column is greater - than 1024, then it cannot write its metadata to binlog properly. - In case of the filename character set with mbmaxlen=5, - the maximum possible character length is 1024/5=204 characters. - Upgrade to VARCHAR if octet length is greater than 1024. - */ - char warn_buff[MYSQL_ERRMSG_SIZE]; - if (thd->is_strict_mode()) - { - my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str, - static_cast(1024 / charset->mbmaxlen)); - DBUG_RETURN(1); - } - set_handler(&type_handler_varchar); - my_snprintf(warn_buff, sizeof(warn_buff), ER_THD(thd, ER_AUTO_CONVERT), - field_name.str, "CHAR", "VARCHAR"); - push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_AUTO_CONVERT, - warn_buff); - } - if (length > MAX_FIELD_VARCHARLENGTH && !(flags & BLOB_FLAG)) { /* Convert long VARCHAR columns to TEXT or BLOB */