mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01: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:
parent
1adc559370
commit
a6dd827a4d
7 changed files with 142 additions and 6 deletions
|
@ -0,0 +1,18 @@
|
|||
RESET MASTER;
|
||||
call mtr.add_suppression("Error in Log_event::read_log_event*");
|
||||
call mtr.add_suppression("Replication event checksum verification failed while reading from a log file*");
|
||||
DROP TABLE /*! IF EXISTS*/ t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 'test.t1'
|
||||
CREATE TABLE `t1` (
|
||||
`col_int` int,
|
||||
pk integer auto_increment,
|
||||
`col_char_12_key` char(12),
|
||||
`col_int_key` int,
|
||||
`col_char_12` char(12),
|
||||
primary key (pk),
|
||||
key (`col_char_12_key` ),
|
||||
key (`col_int_key` )) ENGINE=InnoDB;
|
||||
INSERT /*! IGNORE */ INTO t1 VALUES (183173120, NULL, 'abcd', 1, 'efghijk'), (1, NULL, 'lmno', 2, 'p');
|
||||
ALTER TABLE `t1` ENABLE KEYS;
|
||||
DROP TABLE t1;
|
|
@ -0,0 +1,12 @@
|
|||
RESET MASTER;
|
||||
call mtr.add_suppression("Error in Log_event::read_log_event*");
|
||||
call mtr.add_suppression("Replication event checksum verification failed while reading from a log file*");
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 'test.t1'
|
||||
CREATE TABLE t1 (c1 CHAR(255), c2 CHAR(255), c3 CHAR(255), c4 CHAR(255), c5 CHAR(255));
|
||||
INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
|
||||
INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
|
||||
UPDATE t1 SET c1=repeat('b',255);
|
||||
INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
|
||||
DROP TABLE t1;
|
|
@ -0,0 +1,5 @@
|
|||
[enable_checksum]
|
||||
binlog_checksum=1
|
||||
|
||||
[disable_checksum]
|
||||
binlog_checksum=0
|
48
mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test
Normal file
48
mysql-test/suite/binlog/t/binlog_invalid_read_in_rotate.test
Normal file
|
@ -0,0 +1,48 @@
|
|||
# ==== Purpose ====
|
||||
#
|
||||
# Test verifies that reading binary log by using "SHOW BINLOG EVENTS" command
|
||||
# from various random positions doesn't lead to crash. It should exit
|
||||
# gracefully with appropriate error.
|
||||
#
|
||||
# ==== References ====
|
||||
#
|
||||
# MDEV-18046:Assortment of crashes, assertion failures and ASAN errors in mysql_show_binlog_events
|
||||
|
||||
--source include/have_log_bin.inc
|
||||
--source include/have_innodb.inc
|
||||
|
||||
RESET MASTER;
|
||||
|
||||
call mtr.add_suppression("Error in Log_event::read_log_event*");
|
||||
call mtr.add_suppression("Replication event checksum verification failed while reading from a log file*");
|
||||
|
||||
DROP TABLE /*! IF EXISTS*/ t1;
|
||||
CREATE TABLE `t1` (
|
||||
`col_int` int,
|
||||
pk integer auto_increment,
|
||||
`col_char_12_key` char(12),
|
||||
`col_int_key` int,
|
||||
`col_char_12` char(12),
|
||||
primary key (pk),
|
||||
key (`col_char_12_key` ),
|
||||
key (`col_int_key` )) ENGINE=InnoDB;
|
||||
|
||||
INSERT /*! IGNORE */ INTO t1 VALUES (183173120, NULL, 'abcd', 1, 'efghijk'), (1, NULL, 'lmno', 2, 'p');
|
||||
|
||||
--disable_warnings
|
||||
ALTER TABLE `t1` ENABLE KEYS;
|
||||
--enable_warnings
|
||||
|
||||
--let $max_pos= query_get_value(SHOW MASTER STATUS,Position,1)
|
||||
--let $pos= 1
|
||||
while ($pos <= $max_pos)
|
||||
{
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
--error 0,1220
|
||||
eval SHOW BINLOG EVENTS FROM $pos;
|
||||
--inc $pos
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
}
|
||||
DROP TABLE t1;
|
|
@ -0,0 +1,5 @@
|
|||
[enable_checksum]
|
||||
binlog_checksum=1
|
||||
|
||||
[disable_checksum]
|
||||
binlog_checksum=0
|
|
@ -0,0 +1,37 @@
|
|||
# ==== Purpose ====
|
||||
#
|
||||
# Test verifies that reading binary log by using "SHOW BINLOG EVENTS" command
|
||||
# from various random positions doesn't lead to crash. It should exit
|
||||
# gracefully with appropriate error.
|
||||
#
|
||||
# ==== References ====
|
||||
#
|
||||
# MDEV-18046:Assortment of crashes, assertion failures and ASAN errors in mysql_show_binlog_events
|
||||
|
||||
--source include/have_log_bin.inc
|
||||
--source include/have_innodb.inc
|
||||
|
||||
RESET MASTER;
|
||||
call mtr.add_suppression("Error in Log_event::read_log_event*");
|
||||
call mtr.add_suppression("Replication event checksum verification failed while reading from a log file*");
|
||||
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 CHAR(255), c2 CHAR(255), c3 CHAR(255), c4 CHAR(255), c5 CHAR(255));
|
||||
INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
|
||||
INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
|
||||
UPDATE t1 SET c1=repeat('b',255);
|
||||
INSERT INTO t1 VALUES (repeat('a', 255), repeat('a', 255),repeat('a', 255),repeat('a', 255),repeat('a', 255));
|
||||
--let $max_pos= query_get_value(SHOW MASTER STATUS,Position,1)
|
||||
--let $pos= 1
|
||||
while ($pos <= $max_pos)
|
||||
{
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
--error 0,1220
|
||||
eval SHOW BINLOG EVENTS FROM $pos LIMIT 100;
|
||||
--inc $pos
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
}
|
||||
|
||||
DROP TABLE t1;
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue