From 98d57719e2836af289279528094d9577b7e22d8e Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 8 Nov 2024 11:35:19 +0530 Subject: [PATCH] MDEV-32667 dict_stats_save_index_stat() reads uninitialized index->stats_error_printed Problem: ======== - dict_stats_table_clone_create() does not initialize the flag stats_error_printed in either dict_table_t or dict_index_t. Because dict_stats_save_index_stat() is operating on a copy of a dict_index_t object, it appears that dict_index_t::stats_error_printed will always be false for actual metadata objects, and uninitialized in dict_stats_save_index_stat(). Solution: ========= dict_stats_table_clone_create(): Assign stats_error_printed for table and index while copying the statistics --- mysql-test/suite/innodb/r/stat_tables.result | 16 ++++++++++++++++ mysql-test/suite/innodb/t/stat_tables.test | 13 +++++++++++++ storage/innobase/dict/dict0stats.cc | 3 +++ 3 files changed, 32 insertions(+) diff --git a/mysql-test/suite/innodb/r/stat_tables.result b/mysql-test/suite/innodb/r/stat_tables.result index bb449570479..fe539b4d142 100644 --- a/mysql-test/suite/innodb/r/stat_tables.result +++ b/mysql-test/suite/innodb/r/stat_tables.result @@ -13,3 +13,19 @@ a drop table t1; rename table mysql.table_stats_save to mysql.table_stats; flush tables; +# +# MDEV-32667 dict_stats_save_index_stat() reads uninitialized +# index->stats_error_printed +# +call mtr.add_suppression("InnoDB: Cannot save index statistics for table"); +CREATE TABLE t1(a INT) ENGINE=InnoDB STATS_PERSISTENT=1 STATS_AUTO_RECALC=1; +BEGIN; +SELECT COUNT(*)>=0 FROM mysql.innodb_index_stats LOCK IN SHARE MODE; +COUNT(*)>=0 +1 +INSERT INTO t1 VALUES(0),(0); +SELECT sleep(1); +sleep(1) +0 +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/stat_tables.test b/mysql-test/suite/innodb/t/stat_tables.test index 68344b3f425..932e0e762d7 100644 --- a/mysql-test/suite/innodb/t/stat_tables.test +++ b/mysql-test/suite/innodb/t/stat_tables.test @@ -15,3 +15,16 @@ select * from t1; drop table t1; rename table mysql.table_stats_save to mysql.table_stats; flush tables; + +--echo # +--echo # MDEV-32667 dict_stats_save_index_stat() reads uninitialized +--echo # index->stats_error_printed +--echo # +call mtr.add_suppression("InnoDB: Cannot save index statistics for table"); +CREATE TABLE t1(a INT) ENGINE=InnoDB STATS_PERSISTENT=1 STATS_AUTO_RECALC=1; +BEGIN; +SELECT COUNT(*)>=0 FROM mysql.innodb_index_stats LOCK IN SHARE MODE; +INSERT INTO t1 VALUES(0),(0); +SELECT sleep(1); +COMMIT; +DROP TABLE t1; diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 496a1a5e6f0..485b1916a66 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -423,6 +423,8 @@ dict_stats_table_clone_create( UT_LIST_INIT(t->freed_indexes, &dict_index_t::indexes); #endif /* BTR_CUR_HASH_ADAPT */ + t->stats_error_printed = table->stats_error_printed; + for (index = dict_table_get_first_index(table); index != NULL; index = dict_table_get_next_index(index)) { @@ -479,6 +481,7 @@ dict_stats_table_clone_create( idx->stat_defrag_n_page_split = 0; idx->stat_defrag_n_pages_freed = 0; + idx->stats_error_printed = index->stats_error_printed; } ut_d(t->magic_n = DICT_TABLE_MAGIC_N);