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.
This commit is contained in:
Aleksey Midenkov 2025-04-15 21:49:41 +03:00 committed by Oleksandr Byelkin
parent 837fad6e41
commit 3393d1064f
3 changed files with 47 additions and 0 deletions

View File

@ -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

View File

@ -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 #

View File

@ -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();