Skip to content

Commit 957ec8b

Browse files
committed
MDEV-35622 SEGV, ASAN use-after-poison when reading system table with less than expected number of columns
validate mysql.servers structure
1 parent b163b8f commit 957ec8b

File tree

3 files changed

+84
-5
lines changed

3 files changed

+84
-5
lines changed

mysql-test/main/grant_repair.result

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,13 @@ rename table mysql.roles_mapping to mysql.roles_mapping_bak;
8787
create role r1;
8888
drop role r1;
8989
rename table mysql.roles_mapping_bak to mysql.roles_mapping;
90+
#
91+
# MDEV-35622 SEGV, ASAN use-after-poison when reading system table with less than expected number of columns
92+
#
93+
call mtr.add_suppression("mysql.servers");
94+
alter table mysql.servers drop column owner;
95+
insert into mysql.servers values(0,0,0,0,0,0,0,0);
96+
flush privileges;
97+
ERROR HY000: Cannot load from mysql.servers. The table is probably corrupted
98+
alter table mysql.servers add column Owner varchar(512) not null default '';
9099
# End of 10.11 tests

mysql-test/main/grant_repair.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,14 @@ create role r1;
104104
drop role r1;
105105
rename table mysql.roles_mapping_bak to mysql.roles_mapping;
106106

107+
--echo #
108+
--echo # MDEV-35622 SEGV, ASAN use-after-poison when reading system table with less than expected number of columns
109+
--echo #
110+
call mtr.add_suppression("mysql.servers");
111+
alter table mysql.servers drop column owner;
112+
insert into mysql.servers values(0,0,0,0,0,0,0,0);
113+
--error ER_CANNOT_LOAD_FROM_TABLE_V2
114+
flush privileges;
115+
alter table mysql.servers add column Owner varchar(512) not null default '';
116+
107117
--echo # End of 10.11 tests

sql/sql_servers.cc

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,60 @@ static MEM_ROOT mem;
5656
static mysql_rwlock_t THR_LOCK_servers;
5757
static LEX_CSTRING MYSQL_SERVERS_NAME= {STRING_WITH_LEN("servers") };
5858

59+
static const TABLE_FIELD_TYPE servers_table_fields[] =
60+
{
61+
{
62+
{ STRING_WITH_LEN("Server_name") },
63+
{ STRING_WITH_LEN("char(") },
64+
{ STRING_WITH_LEN("utf8mb") }
65+
},
66+
{
67+
{ STRING_WITH_LEN("Host") },
68+
{ STRING_WITH_LEN("varchar(") },
69+
{ STRING_WITH_LEN("utf8mb") }
70+
},
71+
{
72+
{ STRING_WITH_LEN("Db") },
73+
{ STRING_WITH_LEN("char(") },
74+
{ STRING_WITH_LEN("utf8mb") }
75+
},
76+
{
77+
{ STRING_WITH_LEN("Username") },
78+
{ STRING_WITH_LEN("char(") },
79+
{ STRING_WITH_LEN("utf8mb") }
80+
},
81+
{
82+
{ STRING_WITH_LEN("Password") },
83+
{ STRING_WITH_LEN("char(") },
84+
{ STRING_WITH_LEN("utf8mb") }
85+
},
86+
{
87+
{ STRING_WITH_LEN("Port") },
88+
{ STRING_WITH_LEN("int(") },
89+
{NULL, 0}
90+
},
91+
{
92+
{ STRING_WITH_LEN("Socket") },
93+
{ STRING_WITH_LEN("char(") },
94+
{ STRING_WITH_LEN("utf8mb") }
95+
},
96+
{
97+
{ STRING_WITH_LEN("Wrapper") },
98+
{ STRING_WITH_LEN("char(") },
99+
{ STRING_WITH_LEN("utf8mb") }
100+
},
101+
{
102+
{ STRING_WITH_LEN("Owner") },
103+
{ STRING_WITH_LEN("varchar(") },
104+
{ STRING_WITH_LEN("utf8mb") }
105+
}
106+
};
107+
static const TABLE_FIELD_DEF servers_table_def=
108+
{
109+
array_elements(servers_table_fields), servers_table_fields, 0, NULL
110+
};
111+
112+
static Table_check_intact_log_error table_intact;
59113

60114
static bool get_server_from_table_to_cache(TABLE *table);
61115

@@ -332,17 +386,16 @@ static bool servers_load(THD *thd, TABLE_LIST *tables)
332386

333387
bool servers_reload(THD *thd)
334388
{
335-
TABLE_LIST tables[1];
389+
TABLE_LIST tables;
336390
bool return_val= TRUE;
337391
DBUG_ENTER("servers_reload");
338392

339393
DBUG_PRINT("info", ("locking servers_cache"));
340394
mysql_rwlock_wrlock(&THR_LOCK_servers);
341395

342-
tables[0].init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_SERVERS_NAME, 0, TL_READ);
396+
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_SERVERS_NAME, 0, TL_READ);
343397

344-
if (unlikely(open_and_lock_tables(thd, tables, FALSE,
345-
MYSQL_LOCK_IGNORE_TIMEOUT)))
398+
if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
346399
{
347400
/*
348401
Execution might have been interrupted; only print the error message
@@ -355,7 +408,14 @@ bool servers_reload(THD *thd)
355408
goto end;
356409
}
357410

358-
if ((return_val= servers_load(thd, tables)))
411+
if (table_intact.check(tables.table, &servers_table_def))
412+
{
413+
my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0),
414+
tables.db.str, tables.table_name.str);
415+
goto end;
416+
}
417+
418+
if ((return_val= servers_load(thd, &tables)))
359419
{ // Error. Revert to old list
360420
/* blast, for now, we have no servers, discuss later way to preserve */
361421

0 commit comments

Comments
 (0)