Commit d1eeb4b8 authored by Jan Lindström's avatar Jan Lindström

MDEV-24964 : Heap-buffer-overflow on wsrep_schema.cc ::remove_fragments

Problem was that we used heap allocated key using too small
array. Fixed by using dynamic memory allocation using actual
needed size.
parent f2428b9c
...@@ -566,14 +566,24 @@ static int end_index_scan(TABLE* table) { ...@@ -566,14 +566,24 @@ static int end_index_scan(TABLE* table) {
return 0; return 0;
} }
static void make_key(TABLE* table, uchar* key, key_part_map* map, int parts) { static void make_key(TABLE* table, uchar** key, key_part_map* map, int parts) {
uint prefix_length= 0; uint prefix_length= 0;
KEY_PART_INFO* key_part= table->key_info->key_part; KEY_PART_INFO* key_part= table->key_info->key_part;
for (int i=0; i < parts; i++) for (int i=0; i < parts; i++)
prefix_length += key_part[i].store_length; prefix_length += key_part[i].store_length;
*map= make_prev_keypart_map(parts); *map= make_prev_keypart_map(parts);
key_copy(key, table->record[0], table->key_info, prefix_length);
if (!(*key= (uchar *) my_malloc(prefix_length + 1, MYF(MY_WME))))
{
WSREP_ERROR("Failed to allocate memory for key prefix_length %u", prefix_length);
assert(0);
}
key_copy(*key, table->record[0], table->key_info, prefix_length);
} }
} /* namespace Wsrep_schema_impl */ } /* namespace Wsrep_schema_impl */
...@@ -958,7 +968,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd, ...@@ -958,7 +968,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd,
Wsrep_schema_impl::binlog_off binlog_off(thd); Wsrep_schema_impl::binlog_off binlog_off(thd);
int error; int error;
uchar key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; uchar *key=NULL;
key_part_map key_map= 0; key_part_map key_map= 0;
TABLE* frag_table= 0; TABLE* frag_table= 0;
...@@ -973,7 +983,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd, ...@@ -973,7 +983,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd,
Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id());
Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get());
Wsrep_schema_impl::store(frag_table, 2, -1); Wsrep_schema_impl::store(frag_table, 2, -1);
Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); Wsrep_schema_impl::make_key(frag_table, &key, &key_map, 3);
if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table, if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table,
key, key_map))) key, key_map)))
...@@ -987,9 +997,11 @@ int Wsrep_schema::update_fragment_meta(THD* thd, ...@@ -987,9 +997,11 @@ int Wsrep_schema::update_fragment_meta(THD* thd,
} }
Wsrep_schema_impl::finish_stmt(thd); Wsrep_schema_impl::finish_stmt(thd);
thd->lex->restore_backup_query_tables_list(&query_tables_list_backup); thd->lex->restore_backup_query_tables_list(&query_tables_list_backup);
my_free(key);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
my_free(key);
/* Copy the original record to frag_table->record[1] */ /* Copy the original record to frag_table->record[1] */
store_record(frag_table, record[1]); store_record(frag_table, record[1]);
...@@ -1024,7 +1036,7 @@ static int remove_fragment(THD* thd, ...@@ -1024,7 +1036,7 @@ static int remove_fragment(THD* thd,
seqno.get()); seqno.get());
int ret= 0; int ret= 0;
int error; int error;
uchar key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; uchar *key= NULL;
key_part_map key_map= 0; key_part_map key_map= 0;
DBUG_ASSERT(server_id.is_undefined() == false); DBUG_ASSERT(server_id.is_undefined() == false);
...@@ -1038,7 +1050,7 @@ static int remove_fragment(THD* thd, ...@@ -1038,7 +1050,7 @@ static int remove_fragment(THD* thd,
Wsrep_schema_impl::store(frag_table, 0, server_id); Wsrep_schema_impl::store(frag_table, 0, server_id);
Wsrep_schema_impl::store(frag_table, 1, transaction_id.get()); Wsrep_schema_impl::store(frag_table, 1, transaction_id.get());
Wsrep_schema_impl::store(frag_table, 2, seqno.get()); Wsrep_schema_impl::store(frag_table, 2, seqno.get());
Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); Wsrep_schema_impl::make_key(frag_table, &key, &key_map, 3);
if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table, if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table,
key, key,
...@@ -1060,6 +1072,8 @@ static int remove_fragment(THD* thd, ...@@ -1060,6 +1072,8 @@ static int remove_fragment(THD* thd,
ret= 1; ret= 1;
} }
if (key)
my_free(key);
Wsrep_schema_impl::end_index_scan(frag_table); Wsrep_schema_impl::end_index_scan(frag_table);
return ret; return ret;
} }
...@@ -1147,7 +1161,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1147,7 +1161,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
int ret= 1; int ret= 1;
int error; int error;
TABLE* frag_table= 0; TABLE* frag_table= 0;
uchar key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; uchar *key=NULL;
key_part_map key_map= 0; key_part_map key_map= 0;
for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin(); for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin();
...@@ -1164,7 +1178,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1164,7 +1178,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id());
Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get());
Wsrep_schema_impl::store(frag_table, 2, i->get()); Wsrep_schema_impl::store(frag_table, 2, i->get());
Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); Wsrep_schema_impl::make_key(frag_table, &key, &key_map, 3);
int error= Wsrep_schema_impl::init_for_index_scan(frag_table, int error= Wsrep_schema_impl::init_for_index_scan(frag_table,
key, key,
...@@ -1211,6 +1225,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1211,6 +1225,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
Wsrep_schema_impl::finish_stmt(&thd); Wsrep_schema_impl::finish_stmt(&thd);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
error= Wsrep_schema_impl::init_for_index_scan(frag_table, error= Wsrep_schema_impl::init_for_index_scan(frag_table,
key, key,
key_map); key_map);
...@@ -1224,6 +1239,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1224,6 +1239,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
} }
error= Wsrep_schema_impl::delete_row(frag_table); error= Wsrep_schema_impl::delete_row(frag_table);
if (error) if (error)
{ {
WSREP_WARN("Could not delete row from streaming log table: %d", error); WSREP_WARN("Could not delete row from streaming log table: %d", error);
...@@ -1233,8 +1249,12 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, ...@@ -1233,8 +1249,12 @@ int Wsrep_schema::replay_transaction(THD* orig_thd,
} }
Wsrep_schema_impl::end_index_scan(frag_table); Wsrep_schema_impl::end_index_scan(frag_table);
Wsrep_schema_impl::finish_stmt(&thd); Wsrep_schema_impl::finish_stmt(&thd);
my_free(key);
key= NULL;
} }
if (key)
my_free(key);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment