From 3393d1064f31538b88ea150a2ca1bde83a390836 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 15 Apr 2025 21:49:41 +0300 Subject: [PATCH] MDEV-34075 corruption when query cache cannot allocate block When allocate_block() have failed Query_cache::insert_table() misses to init node->parent which is then accessed with outdated data. There is check in Query_cache::register_all_tables(): if (block_table->parent) unlink_table(block_table); So unlink_table() is avoided when parent is 0. --- mysql-test/main/query_cache.result | 23 +++++++++++++++++++++++ mysql-test/main/query_cache.test | 22 ++++++++++++++++++++++ sql/sql_cache.cc | 2 ++ 3 files changed, 47 insertions(+) diff --git a/mysql-test/main/query_cache.result b/mysql-test/main/query_cache.result index 504aabafda0..db5dc23ef2c 100644 --- a/mysql-test/main/query_cache.result +++ b/mysql-test/main/query_cache.result @@ -2239,6 +2239,29 @@ drop table t1; # set global Query_cache_size=18446744073709547520; # +# MDEV-34075 corruption when query cache cannot allocate block +# +set global query_cache_type=1; +create table t1 (c1 smallint null, c2 binary (25) not null, c3 tinyint(4) null, c4 binary (15) not null primary key, c5 smallint not null unique key,c6 decimal(10,8) not null default 3.141592) engine=innodb; +set global query_cache_size=81920; +select * from t1 where b=1 and c=1; +ERROR 42S22: Unknown column 'b' in 'where clause' +set session query_cache_type=1; +drop table t1; +create table t1 (c1 int not null, c2 char(5)) engine=innodb partition by linear key(c1) partitions 99; +select * from t1 where c1 <='1998-12-29 00:00:00' order by c1,c2; +c1 c2 +select group_concat(a separator '###') as names from t1 having left(names, 1)='j'; +ERROR 42S22: Unknown column 'a' in 'field list' +select * from t1; +c1 c2 +select count(*) from t1; +count(*) +0 +select G.a, c.a from t1 c, t1 G; +ERROR 42S22: Unknown column 'G.a' in 'field list' +drop table t1; +# # End of 10.5 tests # restore defaults diff --git a/mysql-test/main/query_cache.test b/mysql-test/main/query_cache.test index 2a9f34c7cf1..6cd8b886b29 100644 --- a/mysql-test/main/query_cache.test +++ b/mysql-test/main/query_cache.test @@ -2,6 +2,8 @@ -- source include/long_test.inc -- source include/no_valgrind_without_big.inc -- source include/no_view_protocol.inc +-- source include/have_partition.inc +-- source include/have_innodb.inc --disable_ps2_protocol set @save_query_cache_size=@@query_cache_size; @@ -1846,6 +1848,26 @@ drop table t1; set global Query_cache_size=18446744073709547520; --enable_warnings +--echo # +--echo # MDEV-34075 corruption when query cache cannot allocate block +--echo # +set global query_cache_type=1; +create table t1 (c1 smallint null, c2 binary (25) not null, c3 tinyint(4) null, c4 binary (15) not null primary key, c5 smallint not null unique key,c6 decimal(10,8) not null default 3.141592) engine=innodb; +set global query_cache_size=81920; +--error ER_BAD_FIELD_ERROR +select * from t1 where b=1 and c=1; +set session query_cache_type=1; +drop table t1; +create table t1 (c1 int not null, c2 char(5)) engine=innodb partition by linear key(c1) partitions 99; +select * from t1 where c1 <='1998-12-29 00:00:00' order by c1,c2; +--error ER_BAD_FIELD_ERROR +select group_concat(a separator '###') as names from t1 having left(names, 1)='j'; +select * from t1; +select count(*) from t1; +--error ER_BAD_FIELD_ERROR +select G.a, c.a from t1 c, t1 G; +drop table t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index a54d1174e35..e04767d215d 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -3552,6 +3552,7 @@ Query_cache::insert_table(THD *thd, size_t key_len, const char *key, if (table_block == 0) { DBUG_PRINT("qcache", ("Can't write table name to cache")); + node->parent= NULL; DBUG_RETURN(0); } Query_cache_table *header= table_block->table(); @@ -3575,6 +3576,7 @@ Query_cache::insert_table(THD *thd, size_t key_len, const char *key, DBUG_PRINT("qcache", ("Can't insert table to hash")); // write_block_data return locked block free_memory_block(table_block); + node->parent= NULL; DBUG_RETURN(0); } char *db= header->db();