# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2007/11/07 14:59:24+01:00 mats@capulet.net 
#   BUG#31793 (log event corruption causes crash):
#   
#   When running mysqlbinlog on a 64-bit machine with a corrupt relay log,
#   it causes mysqlbinlog to crash. In this case, the crash is caused
#   because a request for 18446744073709534806U bytes is issued, which
#   apparantly can be served on a 64-bit machine (speculatively, I assume)
#   but this causes the memcpy() issued later to copy the data to segfault.
#   
#   The request for the number of bytes is caused by a computation
#   of data_len - server_vars_len where server_vars_len is corrupt in such
#   a sense that it is > data_len. This causes a wrap-around, with the
#   the data_len given above.
#   
#   This patch adds a check that if server_vars_len is greater than
#   data_len before the substraction, and aborts reading the event in
#   that case marking the event as invalid. 
# 
# mysql-test/std_data/corrupt-relay-bin.000624
#   2007/11/07 14:58:30+01:00 mats@capulet.net +2033 -0
#   BitKeeper file /home/mats/devel/b31793-mysql-5.0-rpl/mysql-test/std_data/corrupt-relay-bin.000624
# 
# mysql-test/std_data/corrupt-relay-bin.000624
#   2007/11/07 14:58:30+01:00 mats@capulet.net +0 -0
# 
# mysql-test/t/mysqlbinlog.test
#   2007/11/07 14:59:22+01:00 mats@capulet.net +4 -0
#   Adding test that it fails gracefully for a corrupt relay log.
# 
# sql/log_event.cc
#   2007/11/07 14:59:22+01:00 mats@capulet.net +11 -0
#   Adding check that status var length does not cause wrap-around
#   when performing subtraction.
# 
Binary files a/mysql-test/std_data/corrupt-relay-bin.000624 and b/mysql-test/std_data/corrupt-relay-bin.000624 differ
diff -Nru a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
--- a/mysql-test/t/mysqlbinlog.test	2007-11-07 15:00:13 +01:00
+++ b/mysql-test/t/mysqlbinlog.test	2007-11-07 15:00:13 +01:00
@@ -237,4 +237,8 @@
 --echo $c
 drop table t1;
 
+echo shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql;
+error 1;
+exec $MYSQL_BINLOG $MYSQL_TEST_DIR/std_data/corrupt-relay-bin.000624 > $MYSQLTEST_VARDIR/tmp/bug31793.sql;
+
 --echo End of 5.0 tests
diff -Nru a/sql/log_event.cc b/sql/log_event.cc
--- a/sql/log_event.cc	2007-11-07 15:00:13 +01:00
+++ b/sql/log_event.cc	2007-11-07 15:00:13 +01:00
@@ -1475,6 +1475,17 @@
   if (tmp)
   {
     status_vars_len= uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
+    /*
+      Check if status variable length is corrupt and will lead to very
+      wrong data. We could be even more strict and require data_len to
+      be even bigger, but this will suffice to catch most corruption
+      errors that can lead to a crash.
+    */
+    if (status_vars_len >= data_len + 1)
+    {
+      query= 0;
+      DBUG_VOID_RETURN;
+    }
     data_len-= status_vars_len;
     DBUG_PRINT("info", ("Query_log_event has status_vars_len: %u",
                         (uint) status_vars_len));


