From dea5746de2e604bb1c15892d7f77593e6d7145a2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 16 Jun 2024 18:04:27 +0200 Subject: [PATCH] MDEV-32155 MariaDB Server crashes with ill-formed partitions for ALTER_PARTITION_ADMIN (CHECK/REPAIR/LOAD INDEX/CACHE INDEX/etc) partitioning marks affected partitions with PART_ADMIN state. The assumption is that the server will call a corresponding method of ha_partition which will reset the state back to PART_NORMAL. This assumption is invalid, the server is not required to do so, indeed, in CHECK ... FOR UPGRADE the server might decide early that the table is fine and won't call ha_partition::check(), leaving partitions in the wrong state. It will thus leak into the next statement confusing the engine about what it is doing (see ha_partition::create_handler_file()), causing a crash later. Let's force all partitions into PART_NORMAL state after the admin operation succeeded, in case it did so without consulting the engine. --- mysql-test/main/partition_key_cache.result | 1 - mysql-test/main/partition_key_cache.test | 4 ---- mysql-test/main/partition_mgm_err.result | 13 ++++++++++++- mysql-test/main/partition_mgm_err.test | 17 +++++++++++++---- sql/sql_admin.cc | 4 ++++ 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/mysql-test/main/partition_key_cache.result b/mysql-test/main/partition_key_cache.result index fae7639d9bb..94fa099447b 100644 --- a/mysql-test/main/partition_key_cache.result +++ b/mysql-test/main/partition_key_cache.result @@ -1,4 +1,3 @@ -DROP TABLE IF EXISTS t1, t2, v, x; # Actual test of key caches # Verifing that reads/writes use the key cache correctly SET @org_key_cache_buffer_size= @@global.default.key_buffer_size; diff --git a/mysql-test/main/partition_key_cache.test b/mysql-test/main/partition_key_cache.test index 365a571ae92..a4178d62d65 100644 --- a/mysql-test/main/partition_key_cache.test +++ b/mysql-test/main/partition_key_cache.test @@ -1,10 +1,6 @@ # Test of key cache with partitions --source include/have_partition.inc ---disable_warnings -DROP TABLE IF EXISTS t1, t2, v, x; ---enable_warnings - --echo # Actual test of key caches --echo # Verifing that reads/writes use the key cache correctly SET @org_key_cache_buffer_size= @@global.default.key_buffer_size; diff --git a/mysql-test/main/partition_mgm_err.result b/mysql-test/main/partition_mgm_err.result index 01adc4f5adf..2d523998985 100644 --- a/mysql-test/main/partition_mgm_err.result +++ b/mysql-test/main/partition_mgm_err.result @@ -1,4 +1,3 @@ -drop table if exists t1; CREATE TABLE t1 (a int, b int) PARTITION BY RANGE (a) (PARTITION x0 VALUES LESS THAN (2), @@ -158,3 +157,15 @@ PARTITION p1 VALUES IN (0) (SUBPARTITION p1b), PARTITION p2 VALUES IN (2) (SUBPARTITION p1b) ); ERROR HY000: Duplicate partition name p1b +# End of 5.5 tests +# +# MDEV-32155 MariaDB Server crashes with ill-formed partitions +# +create table t1 (c1 set ( 'abc' ) binary unicode) partition by linear hash (c1 mod c1) partitions 10; +alter table t1 check partition all for upgrade; +Table Op Msg_type Msg_text +test.t1 check status OK +alter table t1 order by nonexistent; +ERROR 42S22: Unknown column 'nonexistent' in 'order clause' +drop table t1; +# End of 10.5 tests diff --git a/mysql-test/main/partition_mgm_err.test b/mysql-test/main/partition_mgm_err.test index 0987c427fc7..61cb82f0c7a 100644 --- a/mysql-test/main/partition_mgm_err.test +++ b/mysql-test/main/partition_mgm_err.test @@ -4,10 +4,6 @@ # -- source include/have_partition.inc ---disable_warnings -drop table if exists t1; ---enable_warnings - # # Try faulty DROP PARTITION and COALESCE PARTITION # @@ -223,3 +219,16 @@ SUBPARTITION BY KEY (s2) ( PARTITION p1 VALUES IN (0) (SUBPARTITION p1b), PARTITION p2 VALUES IN (2) (SUBPARTITION p1b) ); + +--echo # End of 5.5 tests + +--echo # +--echo # MDEV-32155 MariaDB Server crashes with ill-formed partitions +--echo # +create table t1 (c1 set ( 'abc' ) binary unicode) partition by linear hash (c1 mod c1) partitions 10; +alter table t1 check partition all for upgrade; +--error ER_BAD_FIELD_ERROR +alter table t1 order by nonexistent; +drop table t1; + +--echo # End of 10.5 tests diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 3b1ee878b50..9e8d36c475b 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -875,6 +875,10 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, result_code = (table->table->file->*operator_func)(thd, check_opt); THD_STAGE_INFO(thd, stage_sending_data); DBUG_PRINT("admin", ("operator_func returned: %d", result_code)); +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (lex->alter_info.partition_flags & ALTER_PARTITION_ADMIN) + set_part_state(&lex->alter_info, table->table->part_info, PART_NORMAL); +#endif } if (compl_result_code == HA_ADMIN_OK && collect_eis)