Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions mysql-test/suite/binlog/r/fdle_overflow.result
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
SET @saved_dbug= @@GLOBAL.debug_dbug;
SET @@GLOBAL.debug_dbug= '+d,truncate_fde_at_post_header_len';
SET @@GLOBAL.debug_dbug=
'+d,truncate_fde_post_header_len,truncate_fde_used_checksum_alg';
FLUSH BINARY LOGS;
SHOW BINLOG EVENTS IN 'master-bin.000002';
ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error
SET @@GLOBAL.debug_dbug= '+d,truncate_fde_common_header_len';
FLUSH BINARY LOGS;
SHOW BINLOG EVENTS IN 'master-bin.000003';
ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error
SET @@GLOBAL.debug_dbug= @saved_dbug;
RESET MASTER;
7 changes: 6 additions & 1 deletion mysql-test/suite/binlog/t/fdle_overflow.test
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ SET @saved_dbug= @@GLOBAL.debug_dbug;

# MDEV-40366: `used_checksum_alg`

SET @@GLOBAL.debug_dbug= '+d,truncate_fde_at_post_header_len';
SET @@GLOBAL.debug_dbug=
'+d,truncate_fde_post_header_len,truncate_fde_used_checksum_alg';
FLUSH BINARY LOGS;

--let $binlog_file= query_get_value(SHOW BINLOG STATUS, File, 1)
--disable_query_log
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--eval SHOW BINLOG EVENTS IN '$binlog_file'
--enable_query_log


# MDEV-40365: `common_header_len` & `post_header_len`
Expand All @@ -25,8 +28,10 @@ SET @@GLOBAL.debug_dbug= '+d,truncate_fde_common_header_len';
FLUSH BINARY LOGS;

--let $binlog_file= query_get_value(SHOW BINLOG STATUS, File, 1)
--disable_query_log
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--eval SHOW BINLOG EVENTS IN '$binlog_file'
--enable_query_log

# Clean-up
SET @@GLOBAL.debug_dbug= @saved_dbug;
Expand Down
19 changes: 19 additions & 0 deletions mysql-test/suite/rpl/r/rpl_rotate_ev_overflow.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
SET @saved_dbug= @@GLOBAL.debug_dbug;
SET @@GLOBAL.debug_dbug= '+d,truncate_fde_post_header_len';
include/master-slave.inc
[connection master]
FLUSH BINARY LOGS;
CALL mtr.add_suppression('Found invalid event in binary log');
ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error
connection slave;
START SLAVE IO_THREAD;
CALL mtr.add_suppression('Slave I/O: Relay log write failure');
include/wait_for_slave_io_error.inc [errno=1595]
connection master;
SET @@GLOBAL.debug_dbug= @saved_dbug;
RESET MASTER;
connection slave;
CHANGE MASTER TO master_use_gtid=SLAVE_POS;
SET @@GLOBAL.gtid_slave_pos='';
include/start_slave.inc
include/rpl_end.inc
51 changes: 51 additions & 0 deletions mysql-test/suite/rpl/t/rpl_rotate_ev_overflow.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# MDEV-40647 OOB read in IO Thread if the FDEv does not support Rotate Events

--source include/have_debug.inc

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MDEV-40647 requires MSAN to reproduce in CI, but our MSAN CI does not have_debug.
(The alternative is to upload the suspicious binlog the fault injection generates…
Do we want this approach instead?)

--source include/have_binlog_format_mixed.inc # should be format-agnostic

SET @saved_dbug= @@GLOBAL.debug_dbug;
SET @@GLOBAL.debug_dbug= '+d,truncate_fde_post_header_len';
--let $rpl_skip_start_slave= 1
# This setup will also RESET MASTER ...
--source include/master-slave.inc
# ... which means the binlog file is consistent.
--let $binlog_file= master-bin.000001

# Use a specific binlog position to avoid the
# test failing early from other metadata events
--let $binlog_start= query_get_value(SHOW BINLOG STATUS, Position, 1)
# Generate the Rotate Event
FLUSH BINARY LOGS;


# Control: SHOW BINLOG EVENTS fails as expected.
CALL mtr.add_suppression('Found invalid event in binary log');
--disable_query_log
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--eval SHOW BINLOG EVENTS IN '$binlog_file' FROM $binlog_start
--enable_query_log

--connection slave
--disable_query_log
eval CHANGE MASTER TO master_use_gtid=NO,
master_log_file='$binlog_file', master_log_pos=$binlog_start;
--enable_query_log
START SLAVE IO_THREAD;
CALL mtr.add_suppression('Slave I/O: Relay log write failure');
# ER_SLAVE_RELAY_LOG_WRITE_FAILURE
--let $slave_io_errno= 1595
# Experiment: The IO thread should fail.
--source include/wait_for_slave_io_error.inc

# Clean-up
--connection master
SET @@GLOBAL.debug_dbug= @saved_dbug;
RESET MASTER;

--connection slave
CHANGE MASTER TO master_use_gtid=SLAVE_POS; # restore the default
--disable_warnings
SET @@GLOBAL.gtid_slave_pos=''; # for good measure
--enable_warnings
--source include/start_slave.inc
--source include/rpl_end.inc
16 changes: 9 additions & 7 deletions sql/log_event_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2376,8 +2376,9 @@ bool Format_description_log_event::write()
const size_t buff_size= DBUG_EVALUATE_IF("truncate_fde_common_header_len",
ST_COMMON_HEADER_LEN_OFFSET, sizeof(buff));
size_t rec_size= buff_size +
DBUG_EVALUATE_IF("truncate_fde_at_post_header_len", 0,
BINLOG_CHECKSUM_ALG_DESC_LEN + number_of_event_types);
DBUG_EVALUATE_IF("truncate_fde_post_header_len", 0, number_of_event_types) +
DBUG_EVALUATE_IF("truncate_fde_used_checksum_alg", 0,
BINLOG_CHECKSUM_ALG_DESC_LEN);
Comment on lines +2379 to +2381

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I debated with myself whether to simply set some X_size local variables to 0,
but decided that skipping entire write_data() calls is more explicit,
especially considering that an explicit size parameter doesn’t normally make sense for numeric fields.

int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
memcpy((char*) buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
if (!dont_set_created)
Expand Down Expand Up @@ -2416,11 +2417,12 @@ bool Format_description_log_event::write()
checksum_alg= BINLOG_CHECKSUM_ALG_CRC32; // Forcing (V) room to fill anyway
}
ret= write_header(rec_size) ||
write_data(buff, buff_size) ||
DBUG_EVALUATE_IF("truncate_fde_at_post_header_len", false,
write_data(post_header_len, number_of_event_types) ||
write_data(&checksum_byte, sizeof(checksum_byte)) ||
write_footer());
write_data(buff, buff_size) ||
DBUG_EVALUATE_IF("truncate_fde_post_header_len", false,
write_data(post_header_len, number_of_event_types)) ||
DBUG_EVALUATE_IF("truncate_fde_used_checksum_alg", false,
write_data(&checksum_byte, sizeof(checksum_byte))) ||
write_footer();
if (no_checksum)
checksum_alg= BINLOG_CHECKSUM_ALG_OFF;
return ret;
Expand Down
11 changes: 11 additions & 0 deletions sql/slave.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6610,6 +6610,17 @@ static int queue_event(Master_info* mi, const uchar *buf, ulong event_len)
goto err;
case ROTATE_EVENT:
{
/*
It's normally done in Log_event::read_log_event(),
but we bypass it here because it's expensive and costs dynamic memory.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The design oversight behind this is that the IO Thread needs to preprocess certain events, but using Log_event::read_log_event() uniformly is unnecessarily expensive, especially for the events it doesn’t preprocess.

*/
if (unlikely(ROTATE_EVENT >
mi->rli.relay_log.description_event_for_queue->number_of_event_types))
{
// The current FDE does not support `ROTATE_EVENT`.
error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
goto err;
}
Rotate_log_event rev(buf, checksum_alg != BINLOG_CHECKSUM_ALG_OFF ?
event_len - BINLOG_CHECKSUM_LEN : event_len,
mi->rli.relay_log.description_event_for_queue);
Expand Down