mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-33783 CREATE SERVER segfaults on wrong mysql.servers
Do basic checking of mysql.servers compatibility.
This commit is contained in:
@ -24,3 +24,17 @@ SELECT * FROM mysql.servers;
|
|||||||
Server_name Host Db Username Password Port Socket Wrapper Owner
|
Server_name Host Db Username Password Port Socket Wrapper Owner
|
||||||
s1 3306 bar mysql
|
s1 3306 bar mysql
|
||||||
DROP SERVER s1;
|
DROP SERVER s1;
|
||||||
|
#
|
||||||
|
# MDEV-33783 CREATE SERVER segfaults on wrong mysql.servers
|
||||||
|
#
|
||||||
|
create server s1 foreign data wrapper foo options(user 'a');
|
||||||
|
alter server s1 options(host 'server.example.org');
|
||||||
|
rename table mysql.servers to mysql.servers_save;
|
||||||
|
create table mysql.servers (x int);
|
||||||
|
alter server s1 options(host 'server.example.org');
|
||||||
|
ERROR HY000: The foreign server name you are trying to reference does not exist. Data source error: s1
|
||||||
|
create server s2 foreign data wrapper foo options(user 'a');
|
||||||
|
ERROR HY000: Can't read record in system table
|
||||||
|
drop table mysql.servers;
|
||||||
|
rename table mysql.servers_save to mysql.servers;
|
||||||
|
drop server s1;
|
||||||
|
@ -22,3 +22,18 @@ DROP SERVER s1;
|
|||||||
CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS(SOCKET 'bar');
|
CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS(SOCKET 'bar');
|
||||||
SELECT * FROM mysql.servers;
|
SELECT * FROM mysql.servers;
|
||||||
DROP SERVER s1;
|
DROP SERVER s1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-33783 CREATE SERVER segfaults on wrong mysql.servers
|
||||||
|
--echo #
|
||||||
|
create server s1 foreign data wrapper foo options(user 'a');
|
||||||
|
alter server s1 options(host 'server.example.org');
|
||||||
|
rename table mysql.servers to mysql.servers_save;
|
||||||
|
create table mysql.servers (x int);
|
||||||
|
--error ER_FOREIGN_SERVER_DOESNT_EXIST
|
||||||
|
alter server s1 options(host 'server.example.org');
|
||||||
|
--error ER_CANT_FIND_SYSTEM_REC
|
||||||
|
create server s2 foreign data wrapper foo options(user 'a');
|
||||||
|
drop table mysql.servers;
|
||||||
|
rename table mysql.servers_save to mysql.servers;
|
||||||
|
drop server s1;
|
||||||
|
@ -462,7 +462,7 @@ get_server_from_table_to_cache(TABLE *table)
|
|||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
0 - no error
|
0 - no error
|
||||||
other - error code
|
other - ER_ error code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -546,15 +546,19 @@ insert_server_record_into_cache(FOREIGN_SERVER *server)
|
|||||||
advance of insertion into the mysql.servers table
|
advance of insertion into the mysql.servers table
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
VOID
|
0 - no errors
|
||||||
|
>0 - ER_ error code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static int
|
||||||
store_server_fields(TABLE *table, FOREIGN_SERVER *server)
|
store_server_fields(TABLE *table, FOREIGN_SERVER *server)
|
||||||
{
|
{
|
||||||
|
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
|
|
||||||
|
if (table->s->fields < 9)
|
||||||
|
return ER_CANT_FIND_SYSTEM_REC;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
"server" has already been prepped by prepare_server_struct_for_<>
|
"server" has already been prepped by prepare_server_struct_for_<>
|
||||||
so, all we need to do is check if the value is set (> -1 for port)
|
so, all we need to do is check if the value is set (> -1 for port)
|
||||||
@ -563,30 +567,43 @@ store_server_fields(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
have changed will be set. If an insert, then all will be set,
|
have changed will be set. If an insert, then all will be set,
|
||||||
even if with empty strings
|
even if with empty strings
|
||||||
*/
|
*/
|
||||||
if (server->host)
|
if (server->host &&
|
||||||
table->field[1]->store(server->host,
|
table->field[1]->store(server->host,
|
||||||
(uint) strlen(server->host), system_charset_info);
|
(uint) strlen(server->host), system_charset_info))
|
||||||
if (server->db)
|
goto err;
|
||||||
|
if (server->db &&
|
||||||
table->field[2]->store(server->db,
|
table->field[2]->store(server->db,
|
||||||
(uint) strlen(server->db), system_charset_info);
|
(uint) strlen(server->db), system_charset_info))
|
||||||
if (server->username)
|
goto err;
|
||||||
|
if (server->username &&
|
||||||
table->field[3]->store(server->username,
|
table->field[3]->store(server->username,
|
||||||
(uint) strlen(server->username), system_charset_info);
|
(uint) strlen(server->username), system_charset_info))
|
||||||
if (server->password)
|
goto err;
|
||||||
|
if (server->password &&
|
||||||
table->field[4]->store(server->password,
|
table->field[4]->store(server->password,
|
||||||
(uint) strlen(server->password), system_charset_info);
|
(uint) strlen(server->password), system_charset_info))
|
||||||
if (server->port > -1)
|
goto err;
|
||||||
table->field[5]->store(server->port);
|
if (server->port > -1 &&
|
||||||
|
table->field[5]->store(server->port))
|
||||||
if (server->socket)
|
goto err;
|
||||||
|
if (server->socket &&
|
||||||
table->field[6]->store(server->socket,
|
table->field[6]->store(server->socket,
|
||||||
(uint) strlen(server->socket), system_charset_info);
|
(uint) strlen(server->socket), system_charset_info))
|
||||||
if (server->scheme)
|
goto err;
|
||||||
|
if (server->scheme &&
|
||||||
table->field[7]->store(server->scheme,
|
table->field[7]->store(server->scheme,
|
||||||
(uint) strlen(server->scheme), system_charset_info);
|
(uint) strlen(server->scheme), system_charset_info))
|
||||||
if (server->owner)
|
goto err;
|
||||||
|
if (server->owner &&
|
||||||
table->field[8]->store(server->owner,
|
table->field[8]->store(server->owner,
|
||||||
(uint) strlen(server->owner), system_charset_info);
|
(uint) strlen(server->owner), system_charset_info))
|
||||||
|
goto err;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
THD *thd= table->in_use;
|
||||||
|
DBUG_ASSERT(thd->is_error());
|
||||||
|
return thd->get_stmt_da()->get_sql_errno();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -608,7 +625,7 @@ store_server_fields(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 - no errors
|
0 - no errors
|
||||||
>0 - error code
|
>0 - ER_ error code
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -642,7 +659,8 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
error= 1;
|
error= 1;
|
||||||
}
|
}
|
||||||
/* store each field to be inserted */
|
/* store each field to be inserted */
|
||||||
store_server_fields(table, server);
|
if ((error= store_server_fields(table, server)))
|
||||||
|
DBUG_RETURN(error);
|
||||||
|
|
||||||
DBUG_PRINT("info",("record for server '%s' not found!",
|
DBUG_PRINT("info",("record for server '%s' not found!",
|
||||||
server->server_name));
|
server->server_name));
|
||||||
@ -972,9 +990,15 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
|
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
/* set the field that's the PK to the value we're looking for */
|
/* set the field that's the PK to the value we're looking for */
|
||||||
table->field[0]->store(server->server_name,
|
if (table->field[0]->store(server->server_name,
|
||||||
server->server_name_length,
|
server->server_name_length,
|
||||||
system_charset_info);
|
system_charset_info))
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0); /* Protected by servers_cache */
|
||||||
|
THD *thd= table->in_use;
|
||||||
|
DBUG_ASSERT(thd->is_error());
|
||||||
|
return thd->get_stmt_da()->get_sql_errno();
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely((error=
|
if (unlikely((error=
|
||||||
table->file->ha_index_read_idx_map(table->record[0], 0,
|
table->file->ha_index_read_idx_map(table->record[0], 0,
|
||||||
@ -992,7 +1016,8 @@ update_server_record(TABLE *table, FOREIGN_SERVER *server)
|
|||||||
{
|
{
|
||||||
/* ok, so we can update since the record exists in the table */
|
/* ok, so we can update since the record exists in the table */
|
||||||
store_record(table,record[1]);
|
store_record(table,record[1]);
|
||||||
store_server_fields(table, server);
|
if ((error= store_server_fields(table, server)))
|
||||||
|
goto end;
|
||||||
if (unlikely((error=table->file->ha_update_row(table->record[1],
|
if (unlikely((error=table->file->ha_update_row(table->record[1],
|
||||||
table->record[0])) &&
|
table->record[0])) &&
|
||||||
error != HA_ERR_RECORD_IS_THE_SAME))
|
error != HA_ERR_RECORD_IS_THE_SAME))
|
||||||
|
Reference in New Issue
Block a user