MDEV-30945 RPL tests are failing with MSAN use-of-uninitialized-value

...in bitmap_intersect

m_cols_ai was accessed during the Delete event, however this field is only
related to Updates.

Moving it to Update_rows_event would require too much effort. So instead:
* Only access m_cols_ai in Update events (conditional branch is added in
  Rows_log_event::do_add_row_data)
* Clean up m_cols_ai operations in Rows_log_event constructor.
  m_cols_ai.bitmap is first set to NULL, indicating invalid event.
  Then it is initialized:
  -> For Update events, a new bitmap is created.
  -> For other events, debug mode, m_cols_ai.bitmap is set to 1, indicating
     that the value is correct, but it shouldn't be accessed. To make sure
     we'll have a failure, n_bits is also set to 1.
  -> In release mode, m_cols_ai mirrors m_cols, providing extra safety
     in production.
This commit is contained in:
Nikita Malyavin 2023-04-11 00:11:21 +03:00 committed by Sergei Golubchik
parent 2ce2440538
commit 0775c7bdc3
2 changed files with 15 additions and 9 deletions

View file

@ -2972,15 +2972,12 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len,
uint8 const common_header_len= description_event->common_header_len;
Log_event_type event_type= (Log_event_type)(uchar)buf[EVENT_TYPE_OFFSET];
m_type= event_type;
m_cols_ai.bitmap= 0;
m_cols_ai.bitmap= 0; // Set to invalid, so it can be processed in is_valid().
uint8 const post_header_len= description_event->post_header_len[event_type-1];
if (event_len < (uint)(common_header_len + post_header_len))
{
m_cols.bitmap= 0;
DBUG_VOID_RETURN;
}
DBUG_PRINT("enter",("event_len: %u common_header_len: %d "
"post_header_len: %d",
@ -3089,8 +3086,6 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len,
DBUG_VOID_RETURN;
}
m_cols_ai.bitmap= m_cols.bitmap; /* See explanation in is_valid() */
if (LOG_EVENT_IS_UPDATE_ROW(event_type))
{
DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
@ -3109,11 +3104,21 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len,
}
else
{
// Needed because my_bitmap_init() does not set it to null on failure
m_cols_ai.bitmap= 0;
DBUG_ASSERT(m_cols_ai.bitmap == NULL);
DBUG_VOID_RETURN;
}
}
else
{
m_cols_ai= m_cols; /* Safety */
#ifdef DBUG_OFF
/*
m_cols_ai should only be usable for update events. Make sure nobody
successfully manipulates it in debug builds.
*/
m_cols_ai.bitmap= (my_bitmap_map*)1;
#endif
}
const uchar* const ptr_rows_data= (const uchar*) ptr_after_width;

View file

@ -5085,7 +5085,8 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
else
{
bitmap_intersect(table->read_set,&m_cols);
bitmap_intersect(table->write_set, &m_cols_ai);
if (get_general_type_code() == UPDATE_ROWS_EVENT)
bitmap_intersect(table->write_set, &m_cols_ai);
table->mark_columns_per_binlog_row_image();
if (table->vfield)
table->mark_virtual_columns_for_write(0);