mariadb/mysql-test/main/partition_charset.test
Alexander Barkov 4703638775 MDEV-30805 SIGSEGV in my_convert and UBSAN: member access within null pointer of type 'const struct MY_CHARSET_HANDLER' in my_convert
Type_handler::partition_field_append_value() erroneously
passed the address of my_collation_contextually_typed_binary
to conversion functions copy_and_convert() and my_convert().

This happened because generate_partition_syntax_for_frm()
was called from mysql_create_frm_image() in the stage when
the fields in List<Create_field> can still contain unresolved
contextual collations, like "binary" in the reported crash scenario:

  ALTER TABLE t CHANGE COLUMN a a CHAR BINARY;

Fix:

1. Splitting mysql_prepare_create_table() into two parts:
   - mysql_prepare_create_table_stage1() interates through
     List<Create_field> and calls Create_field::prepare_stage1(),
     which performs basic attribute initialization, including
     context collation resolution.
   - mysql_prepare_create_table_finalize() - the rest of the
     old mysql_prepare_create_table() code.

2. Changing mysql_create_frm_image():
   It now calls:
   - mysql_prepare_create_table_stage1() in the very
     beginning, before the partition related code.
   - mysql_prepare_create_table_finalize() in the end,
    instead of the old mysql_prepare_create_table() call

3. Adding mysql_prepare_create_table() as a wrapper
   for two calls:
     mysql_prepare_create_table_stage1() ||
     mysql_prepare_create_table_finalize()
   so the code stays unchanged in the other places
   where mysql_prepare_create_table() was used.

4. Changing prototype for Type_handler::Column_definition_prepare_stage1()
   Removing arguments:
   - handler *file
   - ulonglong table_flags
   Adding a new argument instead:
   - column_definition_type_t type
   This allows to call Column_definition_prepare_stage1() and
   therefore to call mysql_prepare_create_table_stage1()
   before instantiation of a handler.
   This simplifies the code, because in case of a partitioned table,
   mysql_create_frm_image() creates a handler of the underlying
   partition first, the frees it and created a ha_partition
   instance instead.
   mysql_prepare_create_table() before the fix was called with the final
   (ha_partition) handler.

5. Moving parts of Column_definition_prepare_stage1() which
   need a pointer to handler and table_flags to
   Column_definition_prepare_stage2().
2023-03-14 11:50:52 +04:00

49 lines
1.1 KiB
Text

#
# Test for character set related things in combination
# with the partition storage engine
#
-- source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
set names utf8;
create table t1 (s1 int)
partition by list (s1)
(partition c values in (1),
partition Ç values in (3));
insert into t1 values (1),(3);
select * from t1;
flush tables;
set names latin1;
select * from t1;
drop table t1;
-- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED
create table t1 (a varchar(1), primary key (a))
partition by list (ascii(a))
(partition p1 values in (65));
#insert into t1 values ('A');
#replace into t1 values ('A');
#drop table t1;
--echo #
--echo # Start of 10.9 tests
--echo #
--echo #
--echo # MDEV-30805 SIGSEGV in my_convert and UBSAN: member access within null pointer of type 'const struct MY_CHARSET_HANDLER' in my_convert
--echo #
CREATE TABLE t1 (a CHAR CHARACTER SET ucs2)
PARTITION BY RANGE COLUMNS (a)
(PARTITION p0 VALUES LESS THAN ('a'));
ALTER TABLE t1 CHANGE COLUMN a a CHAR BINARY;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # End of 10.9 tests
--echo #