1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-18046: Assortment of crashes, assertion failures and ASAN errors in mysql_show_binlog_events

Problem:
========
SHOW BINLOG EVENTS FROM <pos> causes a variety of failures, some of which are
listed below. It is not a race condition issue, but there is some
non-determinism in it.

Analysis:
========
"show binlog events from <pos>" code considers the user given position as a
valid event start position. The code starts reading data from this event start
position onwards and tries to map it to a set of known events. Each event has
a specific event structure and asserts have been added to ensure that read
event data satisfies the event specific requirements. When a random position
is supplied to "show binlog events command" the event structure specific
checks will fail and they result in assert.

Fix:
====
The fix is split into different parts. Each part addresses either an ASAN
issue or an assert/crash.

**Part1: Checksum based position validation when checksum is enabled**


Using checksum validate the very first event read at the user specified
position. If there is a checksum mismatch report an appropriate error for the
invalid event.
This commit is contained in:
Sujatha
2019-12-18 14:59:44 +05:30
parent 1adc559370
commit a6dd827a4d
7 changed files with 142 additions and 6 deletions

View File

@@ -3840,6 +3840,11 @@ bool mysql_show_binlog_events(THD* thd)
List<Item> field_list;
const char *errmsg = 0;
bool ret = TRUE;
/*
Using checksum validate the correctness of event pos specified in show
binlog events command.
*/
bool verify_checksum_once= false;
IO_CACHE log;
File file = -1;
MYSQL_BIN_LOG *binary_log= NULL;
@@ -3895,6 +3900,10 @@ bool mysql_show_binlog_events(THD* thd)
mi= 0;
}
/* Validate user given position using checksum */
if (lex_mi->pos == pos && !opt_master_verify_checksum)
verify_checksum_once= true;
unit->set_limit(thd->lex->current_select);
limit_start= unit->offset_limit_cnt;
limit_end= unit->select_limit_cnt;
@@ -3977,15 +3986,16 @@ bool mysql_show_binlog_events(THD* thd)
for (event_count = 0;
(ev = Log_event::read_log_event(&log, (mysql_mutex_t*) 0,
description_event,
opt_master_verify_checksum)); )
(opt_master_verify_checksum ||
verify_checksum_once))); )
{
if (event_count >= limit_start &&
ev->net_send(protocol, linfo.log_file_name, pos))
ev->net_send(protocol, linfo.log_file_name, pos))
{
errmsg = "Net error";
delete ev;
errmsg = "Net error";
delete ev;
mysql_mutex_unlock(log_lock);
goto err;
goto err;
}
if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
@@ -4011,10 +4021,11 @@ bool mysql_show_binlog_events(THD* thd)
delete ev;
}
verify_checksum_once= false;
pos = my_b_tell(&log);
if (++event_count >= limit_end)
break;
break;
}
if (event_count < limit_end && log.error)