Fix buffer overflow in COM_FIELD_LIST.
sql/sql_base.cc: Replace strmov() with strnmov() to remove the possibility for buffer overflow. sql/sql_parse.cc: Reject COM_FIELD_LIST with too-big table or wildcard argument. (libmysqlclient doesn't allow sending too long arguments anyway, but we need this to protect against buffer overflow exploits).
This commit is contained in:
parent
e432151e9c
commit
1f683a7270
@ -233,8 +233,12 @@ static void check_unused(void)
|
|||||||
uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list,
|
uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list,
|
||||||
bool tmp_table)
|
bool tmp_table)
|
||||||
{
|
{
|
||||||
uint key_length= (uint) (strmov(strmov(key, table_list->db)+1,
|
char *db_end= strnmov(key, table_list->db, MAX_DBKEY_LENGTH - 2);
|
||||||
table_list->table_name)-key)+1;
|
*db_end++= '\0';
|
||||||
|
char *table_end= strnmov(db_end, table_list->table_name,
|
||||||
|
key + MAX_DBKEY_LENGTH - 1 - db_end);
|
||||||
|
*table_end++= '\0';
|
||||||
|
uint key_length= (uint) (table_end-key);
|
||||||
if (tmp_table)
|
if (tmp_table)
|
||||||
{
|
{
|
||||||
int4store(key + key_length, thd->server_id);
|
int4store(key + key_length, thd->server_id);
|
||||||
|
@ -1304,10 +1304,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
char *fields, *packet_end= packet + packet_length, *arg_end;
|
char *fields, *packet_end= packet + packet_length, *wildcard;
|
||||||
/* Locked closure of all tables */
|
/* Locked closure of all tables */
|
||||||
TABLE_LIST table_list;
|
TABLE_LIST table_list;
|
||||||
LEX_STRING conv_name;
|
char db_buff[NAME_LEN+1];
|
||||||
|
uint32 db_length;
|
||||||
|
uint dummy_errors;
|
||||||
|
|
||||||
/* used as fields initializator */
|
/* used as fields initializator */
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
@ -1319,11 +1321,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
/*
|
/*
|
||||||
We have name + wildcard in packet, separated by endzero
|
We have name + wildcard in packet, separated by endzero
|
||||||
*/
|
*/
|
||||||
arg_end= strend(packet);
|
wildcard= strend(packet);
|
||||||
thd->convert_string(&conv_name, system_charset_info,
|
db_length= wildcard - packet;
|
||||||
packet, (uint) (arg_end - packet), thd->charset());
|
wildcard++;
|
||||||
table_list.alias= table_list.table_name= conv_name.str;
|
uint query_length= (uint) (packet_end - wildcard); // Don't count end \0
|
||||||
packet= arg_end + 1;
|
if (db_length > NAME_LEN || query_length > NAME_LEN)
|
||||||
|
{
|
||||||
|
my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
db_length= copy_and_convert(db_buff, sizeof(db_buff)-1,
|
||||||
|
system_charset_info, packet, db_length,
|
||||||
|
thd->charset(), &dummy_errors);
|
||||||
|
db_buff[db_length]= '\0';
|
||||||
|
table_list.alias= table_list.table_name= db_buff;
|
||||||
|
if (!(fields= (char *) thd->memdup(wildcard, query_length + 1)))
|
||||||
|
break;
|
||||||
|
|
||||||
if (is_schema_db(table_list.db, table_list.db_length))
|
if (is_schema_db(table_list.db, table_list.db_length))
|
||||||
{
|
{
|
||||||
@ -1332,9 +1345,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
table_list.schema_table= schema_table;
|
table_list.schema_table= schema_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint query_length= (uint) (packet_end - packet); // Don't count end \0
|
|
||||||
if (!(fields= (char *) thd->memdup(packet, query_length + 1)))
|
|
||||||
break;
|
|
||||||
thd->set_query(fields, query_length);
|
thd->set_query(fields, query_length);
|
||||||
general_log_print(thd, command, "%s %s", table_list.table_name, fields);
|
general_log_print(thd, command, "%s %s", table_list.table_name, fields);
|
||||||
if (lower_case_table_names)
|
if (lower_case_table_names)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user