1
0
mirror of https://github.com/MariaDB/server.git synced 2025-11-09 11:41:36 +03:00

MDEV-35622 SEGV, ASAN use-after-poison when reading system table with less than expected number of columns

validate mysql.servers structure
This commit is contained in:
Sergei Golubchik
2025-09-30 13:11:03 +02:00
parent b163b8f1c5
commit 957ec8bba6
3 changed files with 84 additions and 5 deletions

View File

@@ -87,4 +87,13 @@ rename table mysql.roles_mapping to mysql.roles_mapping_bak;
create role r1;
drop role r1;
rename table mysql.roles_mapping_bak to mysql.roles_mapping;
#
# MDEV-35622 SEGV, ASAN use-after-poison when reading system table with less than expected number of columns
#
call mtr.add_suppression("mysql.servers");
alter table mysql.servers drop column owner;
insert into mysql.servers values(0,0,0,0,0,0,0,0);
flush privileges;
ERROR HY000: Cannot load from mysql.servers. The table is probably corrupted
alter table mysql.servers add column Owner varchar(512) not null default '';
# End of 10.11 tests

View File

@@ -104,4 +104,14 @@ create role r1;
drop role r1;
rename table mysql.roles_mapping_bak to mysql.roles_mapping;
--echo #
--echo # MDEV-35622 SEGV, ASAN use-after-poison when reading system table with less than expected number of columns
--echo #
call mtr.add_suppression("mysql.servers");
alter table mysql.servers drop column owner;
insert into mysql.servers values(0,0,0,0,0,0,0,0);
--error ER_CANNOT_LOAD_FROM_TABLE_V2
flush privileges;
alter table mysql.servers add column Owner varchar(512) not null default '';
--echo # End of 10.11 tests

View File

@@ -56,6 +56,60 @@ static MEM_ROOT mem;
static mysql_rwlock_t THR_LOCK_servers;
static LEX_CSTRING MYSQL_SERVERS_NAME= {STRING_WITH_LEN("servers") };
static const TABLE_FIELD_TYPE servers_table_fields[] =
{
{
{ STRING_WITH_LEN("Server_name") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Host") },
{ STRING_WITH_LEN("varchar(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Db") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Username") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Password") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Port") },
{ STRING_WITH_LEN("int(") },
{NULL, 0}
},
{
{ STRING_WITH_LEN("Socket") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Wrapper") },
{ STRING_WITH_LEN("char(") },
{ STRING_WITH_LEN("utf8mb") }
},
{
{ STRING_WITH_LEN("Owner") },
{ STRING_WITH_LEN("varchar(") },
{ STRING_WITH_LEN("utf8mb") }
}
};
static const TABLE_FIELD_DEF servers_table_def=
{
array_elements(servers_table_fields), servers_table_fields, 0, NULL
};
static Table_check_intact_log_error table_intact;
static bool get_server_from_table_to_cache(TABLE *table);
@@ -332,17 +386,16 @@ end:
bool servers_reload(THD *thd)
{
TABLE_LIST tables[1];
TABLE_LIST tables;
bool return_val= TRUE;
DBUG_ENTER("servers_reload");
DBUG_PRINT("info", ("locking servers_cache"));
mysql_rwlock_wrlock(&THR_LOCK_servers);
tables[0].init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_SERVERS_NAME, 0, TL_READ);
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_SERVERS_NAME, 0, TL_READ);
if (unlikely(open_and_lock_tables(thd, tables, FALSE,
MYSQL_LOCK_IGNORE_TIMEOUT)))
if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
{
/*
Execution might have been interrupted; only print the error message
@@ -355,7 +408,14 @@ bool servers_reload(THD *thd)
goto end;
}
if ((return_val= servers_load(thd, tables)))
if (table_intact.check(tables.table, &servers_table_def))
{
my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0),
tables.db.str, tables.table_name.str);
goto end;
}
if ((return_val= servers_load(thd, &tables)))
{ // Error. Revert to old list
/* blast, for now, we have no servers, discuss later way to preserve */