summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <sanja@montyprogram.com>2013-09-12 21:36:58 +0300
committerunknown <sanja@montyprogram.com>2013-09-12 21:36:58 +0300
commit7a80c534ad0eb7d71e67999e27d1759d6a8fbf95 (patch)
treeb99b7631d8ff53371c9d9d0852bf6732ba655a5d
parentada15c7a0f7947073664451c3804ab03723c657e (diff)
downloadmariadb-git-7a80c534ad0eb7d71e67999e27d1759d6a8fbf95.tar.gz
MDEV-4645: Incorrect reads of frozen binlog events; FDE corrupted in relay log
Currently several places use description_event->common_header_len instead of LOG_EVENT_MINIMAL_HEADER_LEN when parsing events with "frozen" headers (such as Start_event_v3 and its subclasses such as Format_description_log_event, as well as Rotate_event). This causes events with extra headers (which would otherwise be valid and those headers ignored) to be corrupted due to over-reading or skipping into the data portion of the log events. It is rewritten in some details patch of Jeremy Cole (See MDEV): - The virtual function returns length to avoid IFs (and only one call of the virtual function made) - Printing function avoids printing strings
-rw-r--r--mysql-test/r/mysqlbinlog.result338
-rw-r--r--mysql-test/std_data/mdev-4645-binlog_checksum.binlogbin0 -> 386 bytes
-rw-r--r--mysql-test/std_data/mdev-4645-binlog_group_id.binlogbin0 -> 398 bytes
-rw-r--r--mysql-test/std_data/mdev-4645-binlog_group_id_checksum.binlogbin0 -> 410 bytes
-rw-r--r--mysql-test/std_data/mdev-4645-binlog_none.binlogbin0 -> 374 bytes
-rw-r--r--mysql-test/t/mysqlbinlog.test20
-rw-r--r--sql/log_event.cc274
-rw-r--r--sql/log_event.h5
8 files changed, 542 insertions, 95 deletions
diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result
index 3c8b2ab0a17..007ef38b413 100644
--- a/mysql-test/r/mysqlbinlog.result
+++ b/mysql-test/r/mysqlbinlog.result
@@ -630,7 +630,7 @@ We expect this value to be 2 (one for the INSERT, one for COMMIT).
The bug being tested was that 'Query' lines were not preceded by '#'
If the line is in the table, it had to have been preceded by a '#'
-SELECT COUNT(*) AS `BUG#28293_expect_2` FROM patch WHERE a LIKE '%Query%';
+SELECT COUNT(*) AS `BUG#28293_expect_2` FROM patch WHERE a LIKE '#%Query%';
BUG#28293_expect_2
2
DROP TABLE patch;
@@ -914,3 +914,339 @@ t1
SHOW TABLES IN test;
Tables_in_test
SET GLOBAL SERVER_ID = 1;
+#
+# MDEV-4645: Incorrect reads of frozen binlog events;
+# FDE corrupted in relay log
+#
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at 4
+#130807 23:29:20 server id 1 end_log_pos 106
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 4 |20 ae 02 52 |0f |01 00 00 00 |66 00 00 00 |6a 00 00 00 |00 01
+#
+# 17 04 00 35 2e 31 2e 36 33 2d 67 6f 6f 67 6c 65 2d |..5.1.63-google-|
+# 27 64 65 62 75 67 2d 6c 6f 67 00 00 00 00 00 00 00 |debug-log.......|
+# 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+# 47 00 00 00 00 20 ae 02 52 17 38 0d 00 08 00 12 00 |.... ..R.8......|
+# 57 04 04 04 04 12 00 00 53 00 04 1a 08 00 00 00 08 |.......S........|
+# 67 08 08 02 |...|
+#
+# Event: Start: binlog v 4, server v 5.1.63-google-debug-log created 130807 23:29:20 at startup
+ROLLBACK/*!*/;
+BINLOG '
+IK4CUg8BAAAAZgAAAGoAAAAAAQQANS4xLjYzLWdvb2dsZS1kZWJ1Zy1sb2cAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAgrgJSFzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
+'/*!*/;
+# at 106
+#130807 23:29:24 server id 1 end_log_pos 207
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 6a |24 ae 02 52 |02 |01 00 00 00 |65 00 00 00 |cf 00 00 00 |00 00
+#
+# 81 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 91 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# a1 04 08 00 08 00 08 00 00 63 72 65 61 74 65 20 74 |........create t|
+# b1 61 62 6c 65 20 74 65 73 74 2e 74 31 20 28 69 64 |able test.t1 (id|
+# c1 20 69 6e 74 20 6e 6f 74 20 6e 75 6c 6c 29 | int not null)|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375907364/*!*/;
+SET @@session.pseudo_thread_id=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+create table test.t1 (id int not null)
+/*!*/;
+# at 207
+#130807 23:29:26 server id 1 end_log_pos 305
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# cf |26 ae 02 52 |02 |01 00 00 00 |62 00 00 00 |31 01 00 00 |00 00
+#
+# e6 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# f6 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# 106 04 08 00 08 00 08 00 00 69 6e 73 65 72 74 20 69 |........insert i|
+# 116 6e 74 6f 20 74 65 73 74 2e 74 31 20 28 69 64 29 |nto test.t1 (id)|
+# 126 20 76 61 6c 75 65 73 20 28 31 29 | values (1)|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375907366/*!*/;
+insert into test.t1 (id) values (1)
+/*!*/;
+# at 305
+#130807 23:29:28 server id 1 end_log_pos 386
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 131 |28 ae 02 52 |02 |01 00 00 00 |51 00 00 00 |82 01 00 00 |00 00
+#
+# 148 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 158 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# 168 04 08 00 08 00 08 00 00 64 72 6f 70 20 74 61 62 |........drop tab|
+# 178 6c 65 20 74 65 73 74 2e 74 31 |le test.t1|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375907368/*!*/;
+drop table test.t1
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at 4
+#130807 23:25:35 server id 1 end_log_pos 106
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 4 |3f ad 02 52 |0f |01 00 00 00 |66 00 00 00 |6a 00 00 00 |00 00
+#
+# 17 04 00 35 2e 31 2e 36 33 2d 67 6f 6f 67 6c 65 2d |..5.1.63-google-|
+# 27 64 65 62 75 67 2d 6c 6f 67 00 00 00 00 00 00 00 |debug-log.......|
+# 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+# 47 00 00 00 00 3f ad 02 52 1b 38 0d 00 08 00 12 00 |....?..R.8......|
+# 57 04 04 04 04 12 00 00 53 00 04 1a 08 00 00 00 08 |.......S........|
+# 67 08 08 02 |...|
+#
+# Event: Start: binlog v 4, server v 5.1.63-google-debug-log created 130807 23:25:35 at startup
+ROLLBACK/*!*/;
+BINLOG '
+P60CUg8BAAAAZgAAAGoAAAAAAAQANS4xLjYzLWdvb2dsZS1kZWJ1Zy1sb2cAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAA/rQJSGzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
+'/*!*/;
+# at 106
+#130807 23:25:41 server id 1 end_log_pos 211
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 6a |45 ad 02 52 |02 |01 00 00 00 |69 00 00 00 |d3 00 00 00 |00 00
+#
+# 85 01 00 00 00 01 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 95 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# a5 04 08 00 08 00 08 00 00 63 72 65 61 74 65 20 74 |........create t|
+# b5 61 62 6c 65 20 74 65 73 74 2e 74 31 20 28 69 64 |able test.t1 (id|
+# c5 20 69 6e 74 20 6e 6f 74 20 6e 75 6c 6c 29 | int not null)|
+#
+# Event: Query thread_id=1 exec_time=1 error_code=0
+SET TIMESTAMP=1375907141/*!*/;
+SET @@session.pseudo_thread_id=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+create table test.t1 (id int not null)
+/*!*/;
+# at 211
+#130807 23:25:44 server id 1 end_log_pos 313
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# d3 |48 ad 02 52 |02 |01 00 00 00 |66 00 00 00 |39 01 00 00 |00 00
+#
+# ee 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# fe 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# 10e 04 08 00 08 00 08 00 00 69 6e 73 65 72 74 20 69 |........insert i|
+# 11e 6e 74 6f 20 74 65 73 74 2e 74 31 20 28 69 64 29 |nto test.t1 (id)|
+# 12e 20 76 61 6c 75 65 73 20 28 31 29 | values (1)|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375907144/*!*/;
+insert into test.t1 (id) values (1)
+/*!*/;
+# at 313
+#130807 23:25:48 server id 1 end_log_pos 398
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 139 |4c ad 02 52 |02 |01 00 00 00 |55 00 00 00 |8e 01 00 00 |00 00
+#
+# 154 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 164 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# 174 04 08 00 08 00 08 00 00 64 72 6f 70 20 74 61 62 |........drop tab|
+# 184 6c 65 20 74 65 73 74 2e 74 31 |le test.t1|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375907148/*!*/;
+drop table test.t1
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at 4
+#130807 23:20:55 server id 1 end_log_pos 106
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 4 |27 ac 02 52 |0f |01 00 00 00 |66 00 00 00 |6a 00 00 00 |00 01
+#
+# 17 04 00 35 2e 31 2e 36 33 2d 67 6f 6f 67 6c 65 2d |..5.1.63-google-|
+# 27 64 65 62 75 67 2d 6c 6f 67 00 00 00 00 00 00 00 |debug-log.......|
+# 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+# 47 00 00 00 00 27 ac 02 52 1f 38 0d 00 08 00 12 00 |....'..R.8......|
+# 57 04 04 04 04 12 00 00 53 00 04 1a 08 00 00 00 08 |.......S........|
+# 67 08 08 02 |...|
+#
+# Event: Start: binlog v 4, server v 5.1.63-google-debug-log created 130807 23:20:55 at startup
+ROLLBACK/*!*/;
+BINLOG '
+J6wCUg8BAAAAZgAAAGoAAAAAAQQANS4xLjYzLWdvb2dsZS1kZWJ1Zy1sb2cAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAnrAJSHzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
+'/*!*/;
+# at 106
+#130807 23:21:19 server id 1 end_log_pos 215
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 6a |3f ac 02 52 |02 |01 00 00 00 |6d 00 00 00 |d7 00 00 00 |00 00
+#
+# 89 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 99 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# a9 04 08 00 08 00 08 00 00 63 72 65 61 74 65 20 74 |........create t|
+# b9 61 62 6c 65 20 74 65 73 74 2e 74 31 20 28 69 64 |able test.t1 (id|
+# c9 20 69 6e 74 20 6e 6f 74 20 6e 75 6c 6c 29 | int not null)|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375906879/*!*/;
+SET @@session.pseudo_thread_id=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+create table test.t1 (id int not null)
+/*!*/;
+# at 215
+#130807 23:21:31 server id 1 end_log_pos 321
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# d7 |4b ac 02 52 |02 |01 00 00 00 |6a 00 00 00 |41 01 00 00 |00 00
+#
+# f6 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 106 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# 116 04 08 00 08 00 08 00 00 69 6e 73 65 72 74 20 69 |........insert i|
+# 126 6e 74 6f 20 74 65 73 74 2e 74 31 20 28 69 64 29 |nto test.t1 (id)|
+# 136 20 76 61 6c 75 65 73 20 28 31 29 | values (1)|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375906891/*!*/;
+insert into test.t1 (id) values (1)
+/*!*/;
+# at 321
+#130807 23:21:41 server id 1 end_log_pos 410
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 141 |55 ac 02 52 |02 |01 00 00 00 |59 00 00 00 |9a 01 00 00 |00 00
+#
+# 160 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 170 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# 180 04 08 00 08 00 08 00 00 64 72 6f 70 20 74 61 62 |........drop tab|
+# 190 6c 65 20 74 65 73 74 2e 74 31 |le test.t1|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375906901/*!*/;
+drop table test.t1
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at 4
+#130807 23:38:51 server id 1 end_log_pos 106
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 4 |5b b0 02 52 |0f |01 00 00 00 |66 00 00 00 |6a 00 00 00 |00 00
+#
+# 17 04 00 35 2e 31 2e 36 33 2d 67 6f 6f 67 6c 65 2d |..5.1.63-google-|
+# 27 64 65 62 75 67 2d 6c 6f 67 00 00 00 00 00 00 00 |debug-log.......|
+# 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+# 47 00 00 00 00 5b b0 02 52 13 38 0d 00 08 00 12 00 |....[..R.8......|
+# 57 04 04 04 04 12 00 00 53 00 04 1a 08 00 00 00 08 |.......S........|
+# 67 08 08 02 |...|
+#
+# Event: Start: binlog v 4, server v 5.1.63-google-debug-log created 130807 23:38:51 at startup
+ROLLBACK/*!*/;
+BINLOG '
+W7ACUg8BAAAAZgAAAGoAAAAAAAQANS4xLjYzLWdvb2dsZS1kZWJ1Zy1sb2cAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAABbsAJSEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
+'/*!*/;
+# at 106
+#130807 23:38:53 server id 1 end_log_pos 203
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 6a |5d b0 02 52 |02 |01 00 00 00 |61 00 00 00 |cb 00 00 00 |00 00
+#
+# 7d 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 8d 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# 9d 04 08 00 08 00 08 00 00 63 72 65 61 74 65 20 74 |........create t|
+# ad 61 62 6c 65 20 74 65 73 74 2e 74 31 20 28 69 64 |able test.t1 (id|
+# bd 20 69 6e 74 20 6e 6f 74 20 6e 75 6c 6c 29 | int not null)|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375907933/*!*/;
+SET @@session.pseudo_thread_id=1/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=0/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+create table test.t1 (id int not null)
+/*!*/;
+# at 203
+#130807 23:38:55 server id 1 end_log_pos 297
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# cb |5f b0 02 52 |02 |01 00 00 00 |5e 00 00 00 |29 01 00 00 |00 00
+#
+# de 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# ee 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# fe 04 08 00 08 00 08 00 00 69 6e 73 65 72 74 20 69 |........insert i|
+# 10e 6e 74 6f 20 74 65 73 74 2e 74 31 20 28 69 64 29 |nto test.t1 (id)|
+# 11e 20 76 61 6c 75 65 73 20 28 31 29 | values (1)|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375907935/*!*/;
+insert into test.t1 (id) values (1)
+/*!*/;
+# at 297
+#130807 23:38:57 server id 1 end_log_pos 374
+# Position
+# |Timestamp |Type |Master ID |Size |Master Pos |Flags
+# 129 |61 b0 02 52 |02 |01 00 00 00 |4d 00 00 00 |76 01 00 00 |00 00
+#
+# 13c 01 00 00 00 00 00 00 00 00 00 00 1a 00 00 00 40 |...............@|
+# 14c 00 00 01 00 00 00 00 00 00 00 00 06 03 73 74 64 |.............std|
+# 15c 04 08 00 08 00 08 00 00 64 72 6f 70 20 74 61 62 |........drop tab|
+# 16c 6c 65 20 74 65 73 74 2e 74 31 |le test.t1|
+#
+# Event: Query thread_id=1 exec_time=0 error_code=0
+SET TIMESTAMP=1375907937/*!*/;
+drop table test.t1
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
diff --git a/mysql-test/std_data/mdev-4645-binlog_checksum.binlog b/mysql-test/std_data/mdev-4645-binlog_checksum.binlog
new file mode 100644
index 00000000000..861e9b4fd67
--- /dev/null
+++ b/mysql-test/std_data/mdev-4645-binlog_checksum.binlog
Binary files differ
diff --git a/mysql-test/std_data/mdev-4645-binlog_group_id.binlog b/mysql-test/std_data/mdev-4645-binlog_group_id.binlog
new file mode 100644
index 00000000000..a9a6722bea2
--- /dev/null
+++ b/mysql-test/std_data/mdev-4645-binlog_group_id.binlog
Binary files differ
diff --git a/mysql-test/std_data/mdev-4645-binlog_group_id_checksum.binlog b/mysql-test/std_data/mdev-4645-binlog_group_id_checksum.binlog
new file mode 100644
index 00000000000..a936ffb139a
--- /dev/null
+++ b/mysql-test/std_data/mdev-4645-binlog_group_id_checksum.binlog
Binary files differ
diff --git a/mysql-test/std_data/mdev-4645-binlog_none.binlog b/mysql-test/std_data/mdev-4645-binlog_none.binlog
new file mode 100644
index 00000000000..7ceeca9e8c1
--- /dev/null
+++ b/mysql-test/std_data/mdev-4645-binlog_none.binlog
Binary files differ
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index 96b18be8c37..d492af92cb2 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -275,17 +275,16 @@ FLUSH LOGS;
DROP TABLE t1;
-# We create a table, patch, and load the output into it
-# By using LINES STARTING BY '#' + SELECT WHERE a LIKE 'Query'
-# We can easily see if a 'Query' line is missing the '#' character
-# as described in the original bug
+# We create a table named "patch", and load the output into it.
+# By using LIKE, we can easily see if the output is missing the '#'
+# character, as described in the bug.
--disable_query_log
CREATE TABLE patch (a BLOB);
--exec $MYSQL_BINLOG --hexdump --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLD_DATADIR/master-bin.000012 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_tmp.dat
### Starting master-bin.000014
eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_tmp.dat'
- INTO TABLE patch FIELDS TERMINATED BY '' LINES STARTING BY '#';
+ INTO TABLE patch FIELDS TERMINATED BY '';
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_tmp.dat
--enable_query_log
@@ -293,7 +292,7 @@ eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_tmp.dat'
--echo The bug being tested was that 'Query' lines were not preceded by '#'
--echo If the line is in the table, it had to have been preceded by a '#'
--echo
-SELECT COUNT(*) AS `BUG#28293_expect_2` FROM patch WHERE a LIKE '%Query%';
+SELECT COUNT(*) AS `BUG#28293_expect_2` FROM patch WHERE a LIKE '#%Query%';
DROP TABLE patch;
#
@@ -594,3 +593,12 @@ SHOW TABLES IN test;
--exec $MYSQL_BINLOG --server-id=2 $MYSQLD_DATADIR/$master_binlog | $MYSQL
SHOW TABLES IN test;
eval SET GLOBAL SERVER_ID = $old_server_id;
+
+--echo #
+--echo # MDEV-4645: Incorrect reads of frozen binlog events;
+--echo # FDE corrupted in relay log
+--echo #
+--exec $MYSQL_BINLOG --hexdump std_data/mdev-4645-binlog_checksum.binlog
+--exec $MYSQL_BINLOG --hexdump std_data/mdev-4645-binlog_group_id.binlog
+--exec $MYSQL_BINLOG --hexdump std_data/mdev-4645-binlog_group_id_checksum.binlog
+--exec $MYSQL_BINLOG --hexdump std_data/mdev-4645-binlog_none.binlog
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 51fa9d77267..b0380686e0f 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1755,6 +1755,165 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
#ifdef MYSQL_CLIENT
+static void hexdump_minimal_header_to_io_cache(IO_CACHE *file,
+ my_off_t offset,
+ uchar *ptr)
+{
+ DBUG_ASSERT(LOG_EVENT_MINIMAL_HEADER_LEN == 19);
+
+ /*
+ Pretty-print the first LOG_EVENT_MINIMAL_HEADER_LEN (19) bytes of the
+ common header, which contains the basic information about the log event.
+ Every event will have at least this much header, but events could contain
+ more headers (which must be printed by other methods, if desired).
+ */
+ char emit_buf[120]; // Enough for storing one line
+ my_b_printf(file,
+ "# "
+ "|Timestamp "
+ "|Type "
+ "|Master ID "
+ "|Size "
+ "|Master Pos "
+ "|Flags\n");
+ size_t const emit_buf_written=
+ my_snprintf(emit_buf, sizeof(emit_buf),
+ "# %8llx " /* Position */
+ "|%02x %02x %02x %02x " /* Timestamp */
+ "|%02x " /* Type */
+ "|%02x %02x %02x %02x " /* Master ID */
+ "|%02x %02x %02x %02x " /* Size */
+ "|%02x %02x %02x %02x " /* Master Pos */
+ "|%02x %02x\n", /* Flags */
+ (ulonglong) offset, /* Position */
+ ptr[0], ptr[1], ptr[2], ptr[3], /* Timestamp */
+ ptr[4], /* Type */
+ ptr[5], ptr[6], ptr[7], ptr[8], /* Master ID */
+ ptr[9], ptr[10], ptr[11], ptr[12], /* Size */
+ ptr[13], ptr[14], ptr[15], ptr[16], /* Master Pos */
+ ptr[17], ptr[18]); /* Flags */
+
+ DBUG_ASSERT(static_cast<size_t>(emit_buf_written) < sizeof(emit_buf));
+ my_b_write(file, reinterpret_cast<uchar*>(emit_buf), emit_buf_written);
+ my_b_write(file, "#\n", 2);
+}
+
+
+/*
+ The number of bytes to print per line. Should be an even number,
+ and "hexdump -C" uses 16, so we'll duplicate that here.
+*/
+#define HEXDUMP_BYTES_PER_LINE 16
+
+static void format_hex_line(char *emit_buff)
+{
+ memset(emit_buff + 1, ' ',
+ 1 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE);
+ emit_buff[0]= '#';
+ emit_buff[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 1]= '|';
+ emit_buff[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE]= '|';
+ emit_buff[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE + 1]= '\n';
+ emit_buff[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE + 2]= '\0';
+}
+
+static void hexdump_data_to_io_cache(IO_CACHE *file,
+ my_off_t offset,
+ uchar *ptr,
+ my_off_t size)
+{
+ /*
+ 2 = '# '
+ 8 = address
+ 2 = ' '
+ (HEXDUMP_BYTES_PER_LINE * 3 + 1) = Each byte prints as two hex digits,
+ plus a space
+ 2 = ' |'
+ HEXDUMP_BYTES_PER_LINE = text representation
+ 2 = '|\n'
+ 1 = '\0'
+ */
+ char emit_buffer[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE + 2 + 1 ];
+ char *h,*c;
+ my_off_t i;
+
+ if (size == 0)
+ return;
+
+ format_hex_line(emit_buffer);
+ /*
+ Print the rest of the event (without common header)
+ */
+ my_off_t starting_offset = offset;
+ for (i= 0,
+ c= emit_buffer + 2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2,
+ h= emit_buffer + 2 + 8 + 2;
+ i < size;
+ i++, ptr++)
+ {
+ my_snprintf(h, 4, "%02x ", *ptr);
+ h+= 3;
+
+ *c++= my_isprint(&my_charset_bin, *ptr) ? *ptr : '.';
+
+ /* Print in groups of HEXDUMP_BYTES_PER_LINE characters. */
+ if ((i % HEXDUMP_BYTES_PER_LINE) == (HEXDUMP_BYTES_PER_LINE - 1))
+ {
+ /* remove \0 left after printing hex byte representation */
+ *h= ' ';
+ /* prepare space to print address */
+ memset(emit_buffer + 2, ' ', 8);
+ /* print address */
+ size_t const emit_buf_written= my_snprintf(emit_buffer + 2, 9, "%8llx",
+ (ulonglong) starting_offset);
+ /* remove \0 left after printing address */
+ emit_buffer[2 + emit_buf_written]= ' ';
+ my_b_write(file, reinterpret_cast<uchar*>(emit_buffer),
+ sizeof(emit_buffer) - 1);
+ c= emit_buffer + 2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2;
+ h= emit_buffer + 2 + 8 + 2;
+ format_hex_line(emit_buffer);
+ starting_offset+= HEXDUMP_BYTES_PER_LINE;
+ }
+ else if ((i % (HEXDUMP_BYTES_PER_LINE / 2))
+ == ((HEXDUMP_BYTES_PER_LINE / 2) - 1))
+ {
+ /*
+ In the middle of the group of HEXDUMP_BYTES_PER_LINE, emit an extra
+ space in the hex string, to make two groups.
+ */
+ *h++= ' ';
+ }
+
+ }
+
+ /*
+ There is still data left in our buffer, which means that the previous
+ line was not perfectly HEXDUMP_BYTES_PER_LINE characters, so write an
+ incomplete line, with spaces to pad out to the same length as a full
+ line would be, to make things more readable.
+ */
+ if (h != emit_buffer + 2 + 8 + 2)
+ {
+ *h= ' ';
+ *c++= '|'; *c++= '\n';
+ memset(emit_buffer + 2, ' ', 8);
+ size_t const emit_buf_written= my_snprintf(emit_buffer + 2, 9, "%8llx",
+ (ulonglong) starting_offset);
+ emit_buffer[2 + emit_buf_written]= ' ';
+ /* pad unprinted area */
+ memset(h, ' ',
+ (HEXDUMP_BYTES_PER_LINE * 3 + 1) - (h - (emit_buffer + 2 + 8 + 2)));
+ my_b_write(file, reinterpret_cast<uchar*>(emit_buffer),
+ c - emit_buffer);
+ }
+ my_b_write(file, "#\n", 2);
+}
+
/*
Log_event::print_header()
*/
@@ -1789,86 +1948,27 @@ void Log_event::print_header(IO_CACHE* file,
{
my_b_printf(file, "\n");
uchar *ptr= (uchar*)temp_buf;
- my_off_t size=
- uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN;
- my_off_t i;
-
- /* Header len * 4 >= header len * (2 chars + space + extra space) */
- char *h, hex_string[LOG_EVENT_MINIMAL_HEADER_LEN*4]= {0};
- char *c, char_string[16+1]= {0};
-
- /* Pretty-print event common header if header is exactly 19 bytes */
- if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN)
- {
- char emit_buf[256]; // Enough for storing one line
- my_b_printf(file, "# Position Timestamp Type Master ID "
- "Size Master Pos Flags \n");
- size_t const bytes_written=
- my_snprintf(emit_buf, sizeof(emit_buf),
- "# %8.8lx %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x\n",
- (unsigned long) hexdump_from,
- ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6],
- ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13],
- ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
- DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
- my_b_write(file, (uchar*) emit_buf, bytes_written);
- ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
- hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
- }
-
- /* Rest of event (without common header) */
- for (i= 0, c= char_string, h=hex_string;
- i < size;
- i++, ptr++)
- {
- my_snprintf(h, 4, "%02x ", *ptr);
- h += 3;
-
- *c++= my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.';
-
- if (i % 16 == 15)
- {
- /*
- my_b_printf() does not support full printf() formats, so we
- have to do it this way.
+ my_off_t size= uint4korr(ptr + EVENT_LEN_OFFSET);
+ my_off_t hdr_len= get_header_len(print_event_info->common_header_len);
- TODO: Rewrite my_b_printf() to support full printf() syntax.
- */
- char emit_buf[256];
- size_t const bytes_written=
- my_snprintf(emit_buf, sizeof(emit_buf),
- "# %8.8lx %-48.48s |%16s|\n",
- (unsigned long) (hexdump_from + (i & 0xfffffff0)),
- hex_string, char_string);
- DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
- my_b_write(file, (uchar*) emit_buf, bytes_written);
- hex_string[0]= 0;
- char_string[0]= 0;
- c= char_string;
- h= hex_string;
- }
- else if (i % 8 == 7) *h++ = ' ';
- }
- *c= '\0';
+ size-= hdr_len;
+
+ my_b_printf(file, "# Position\n");
+
+ /* Write the header, nicely formatted by field. */
+ hexdump_minimal_header_to_io_cache(file, hexdump_from, ptr);
+
+ ptr+= hdr_len;
+ hexdump_from+= hdr_len;
+
+ /* Print the rest of the data, mimicking "hexdump -C" output. */
+ hexdump_data_to_io_cache(file, hexdump_from, ptr, size);
- if (hex_string[0])
- {
- char emit_buf[256];
- size_t const bytes_written=
- my_snprintf(emit_buf, sizeof(emit_buf),
- "# %8.8lx %-48.48s |%s|\n",
- (unsigned long) (hexdump_from + (i & 0xfffffff0)),
- hex_string, char_string);
- DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
- my_b_write(file, (uchar*) emit_buf, bytes_written);
- }
/*
- need a # to prefix the rest of printouts for example those of
- Rows_log_event::print_helper().
+ Prefix the next line so that the output from print_helper()
+ will appear as a comment.
*/
- my_b_write(file, reinterpret_cast<const uchar*>("# "), 2);
+ my_b_write(file, "# Event: ", 9);
}
DBUG_VOID_RETURN;
}
@@ -4407,7 +4507,7 @@ Start_log_event_v3::Start_log_event_v3(const char* buf,
*description_event)
:Log_event(buf, description_event)
{
- buf+= description_event->common_header_len;
+ buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
ST_SERVER_VER_LEN);
@@ -4762,7 +4862,7 @@ bool Format_description_log_event::write(IO_CACHE* file)
if (!dont_set_created)
created= get_time();
int4store(buff + ST_CREATED_OFFSET,created);
- buff[ST_COMMON_HEADER_LEN_OFFSET]= LOG_EVENT_HEADER_LEN;
+ buff[ST_COMMON_HEADER_LEN_OFFSET]= common_header_len;
/*
if checksum is requested
record the checksum-algorithm descriptor next to
@@ -4989,9 +5089,9 @@ uint8 get_checksum_alg(const char* buf, ulong len)
DBUG_ENTER("get_checksum_alg");
DBUG_ASSERT(buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT);
- memcpy(version, buf +
- buf[LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET]
- + ST_SERVER_VER_OFFSET, ST_SERVER_VER_LEN);
+ memcpy(version,
+ buf + LOG_EVENT_MINIMAL_HEADER_LEN + ST_SERVER_VER_OFFSET,
+ ST_SERVER_VER_LEN);
version[ST_SERVER_VER_LEN - 1]= 0;
do_server_version_split(version, &version_split);
@@ -5863,16 +5963,14 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
{
DBUG_ENTER("Rotate_log_event::Rotate_log_event(char*,...)");
// The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
- uint8 header_size= description_event->common_header_len;
uint8 post_header_len= description_event->post_header_len[ROTATE_EVENT-1];
uint ident_offset;
- if (event_len < header_size)
+ if (event_len < LOG_EVENT_MINIMAL_HEADER_LEN)
DBUG_VOID_RETURN;
- buf += header_size;
- pos = post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4;
- ident_len = (uint)(event_len -
- (header_size+post_header_len));
- ident_offset = post_header_len;
+ buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
+ pos= post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4;
+ ident_len= (uint)(event_len - (LOG_EVENT_MINIMAL_HEADER_LEN + post_header_len));
+ ident_offset= post_header_len;
set_if_smaller(ident_len,FN_REFLEN-1);
new_log_ident= my_strndup(buf + ident_offset, (uint) ident_len, MYF(MY_WME));
DBUG_PRINT("debug", ("new_log_ident: '%s'", new_log_ident));
diff --git a/sql/log_event.h b/sql/log_event.h
index 39a6ce24036..9a74203757c 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -1253,6 +1253,7 @@ public:
#endif
virtual Log_event_type get_type_code() = 0;
virtual bool is_valid() const = 0;
+ virtual my_off_t get_header_len(my_off_t len) { return len; }
void set_artificial_event() { flags |= LOG_EVENT_ARTIFICIAL_F; }
void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; }
bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F; }
@@ -2469,6 +2470,8 @@ public:
const Format_description_log_event* description_event);
~Start_log_event_v3() {}
Log_event_type get_type_code() { return START_EVENT_V3;}
+ my_off_t get_header_len(my_off_t l __attribute__((unused)))
+ { return LOG_EVENT_MINIMAL_HEADER_LEN; }
#ifdef MYSQL_SERVER
bool write(IO_CACHE* file);
#endif
@@ -2984,6 +2987,8 @@ public:
my_free((void*) new_log_ident);
}
Log_event_type get_type_code() { return ROTATE_EVENT;}
+ my_off_t get_header_len(my_off_t l __attribute__((unused)))
+ { return LOG_EVENT_MINIMAL_HEADER_LEN; }
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() const { return new_log_ident != 0; }
#ifdef MYSQL_SERVER