List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:May 4 2011 1:23pm
Subject:bzr push into mysql-5.1 branch (alexander.nozdrin:3680 to 3681) Bug#12394306
View as plain text  
 3681 Alexander Nozdrin	2011-05-04
      Patch for Bug#12394306: the sever may crash if mysql.event is corrupted.
      
      The problem was that wrong structure of mysql.event was not detected and
      the server continued to use wrongly-structured data.
      
      The fix is to check the structure of mysql.event after opening before
      any use. That makes operations with events more strict -- some operations
      that might work before throw errors now. That seems to be Ok.
      
      Another side-effect of the patch is that if mysql.event is corrupted,
      unrelated DROP DATABASE statements issue an SQL warning about inability
      to open mysql.event table. 

    modified:
      mysql-test/r/events_1.result
      mysql-test/r/events_restart.result
      mysql-test/t/events_1.test
      mysql-test/t/events_restart.test
      sql/event_db_repository.cc
 3680 Kent Boortz	2011-05-03
      Remove soft links in the build directory, not the source directory (Bug#43312)

    modified:
      client/Makefile.am
=== modified file 'mysql-test/r/events_1.result'
--- a/mysql-test/r/events_1.result	2008-02-20 13:40:46 +0000
+++ b/mysql-test/r/events_1.result	2011-05-04 12:59:24 +0000
@@ -1,3 +1,4 @@
+call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted");
 drop database if exists events_test;
 drop database if exists db_x;
 drop database if exists mysqltest_db2;
@@ -259,33 +260,36 @@ events_test	intact_check	root@localhost
 Try to alter mysql.event: the server should fail to load
 event information after mysql.event was tampered with.
 
-First, let's add a column to the end and make sure everything
-works as before
+First, let's add a column to the end and check the error is emitted.
 
 ALTER TABLE mysql.event ADD dummy INT;
 SHOW EVENTS;
-Db	Name	Definer	Time zone	Type	Execute at	Interval value	Interval field	Starts	Ends	Status	Originator	character_set_client	collation_connection	Database Collation
-events_test	intact_check	root@localhost	SYSTEM	RECURRING	NULL	10	#	#	NULL	ENABLED	1	latin1	latin1_swedish_ci	latin1_swedish_ci
+ERROR HY000: Failed to open mysql.event
 SELECT event_name FROM INFORMATION_SCHEMA.events;
-event_name
-intact_check
+ERROR HY000: Failed to open mysql.event
 SHOW CREATE EVENT intact_check;
-Event	sql_mode	time_zone	Create Event	character_set_client	collation_connection	Database Collation
-intact_check		SYSTEM	CREATE EVENT `intact_check` ON SCHEDULE EVERY 10 HOUR STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO SELECT "nothing"	latin1	latin1_swedish_ci	latin1_swedish_ci
+ERROR HY000: Failed to open mysql.event
 DROP EVENT no_such_event;
-ERROR HY000: Unknown event 'no_such_event'
+ERROR HY000: Failed to open mysql.event
 CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
+ERROR HY000: Failed to open mysql.event
 ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
+ERROR HY000: Failed to open mysql.event
 ALTER EVENT intact_check_1 RENAME TO intact_check_2;
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check_1;
-ERROR HY000: Unknown event 'intact_check_1'
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check_2;
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check;
+ERROR HY000: Failed to open mysql.event
 DROP DATABASE IF EXISTS mysqltest_no_such_database;
 Warnings:
 Note	1008	Can't drop database 'mysqltest_no_such_database'; database doesn't exist
 CREATE DATABASE mysqltest_db2;
 DROP DATABASE mysqltest_db2;
+Warnings:
+Error	1545	Failed to open mysql.event
 SELECT @@event_scheduler;
 @@event_scheduler
 OFF
@@ -294,6 +298,7 @@ Variable_name	Value
 event_scheduler	OFF
 SET GLOBAL event_scheduler=OFF;
 ALTER TABLE mysql.event DROP dummy;
+DROP EVENT intact_check;
 CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
 
 Now let's add a column to the first position: the server
@@ -301,30 +306,32 @@ expects to see event schema name there
 
 ALTER TABLE mysql.event ADD dummy INT FIRST;
 SHOW EVENTS;
-ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
+ERROR HY000: Failed to open mysql.event
 SELECT event_name FROM INFORMATION_SCHEMA.events;
-ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
+ERROR HY000: Failed to open mysql.event
 SHOW CREATE EVENT intact_check;
-ERROR HY000: Unknown event 'intact_check'
+ERROR HY000: Failed to open mysql.event
 DROP EVENT no_such_event;
-ERROR HY000: Unknown event 'no_such_event'
+ERROR HY000: Failed to open mysql.event
 CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
-ERROR HY000: Failed to store event name. Error code 2 from storage engine.
+ERROR HY000: Failed to open mysql.event
 ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
-ERROR HY000: Unknown event 'intact_check_1'
+ERROR HY000: Failed to open mysql.event
 ALTER EVENT intact_check_1 RENAME TO intact_check_2;
-ERROR HY000: Unknown event 'intact_check_1'
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check_1;
-ERROR HY000: Unknown event 'intact_check_1'
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check_2;
-ERROR HY000: Unknown event 'intact_check_2'
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check;
-ERROR HY000: Unknown event 'intact_check'
+ERROR HY000: Failed to open mysql.event
 DROP DATABASE IF EXISTS mysqltest_no_such_database;
 Warnings:
 Note	1008	Can't drop database 'mysqltest_no_such_database'; database doesn't exist
 CREATE DATABASE mysqltest_db2;
 DROP DATABASE mysqltest_db2;
+Warnings:
+Error	1545	Failed to open mysql.event
 SELECT @@event_scheduler;
 @@event_scheduler
 OFF
@@ -345,29 +352,32 @@ Drop some columns and try more checks.
 
 ALTER TABLE mysql.event DROP comment, DROP starts;
 SHOW EVENTS;
-ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
+ERROR HY000: Failed to open mysql.event
 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
-ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
+ERROR HY000: Failed to open mysql.event
 SHOW CREATE EVENT intact_check;
-ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
+ERROR HY000: Failed to open mysql.event
 DROP EVENT no_such_event;
-ERROR HY000: Unknown event 'no_such_event'
+ERROR HY000: Failed to open mysql.event
 CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
-ERROR HY000: Column count of mysql.event is wrong. Expected 22, found 20. The table is probably corrupted
+ERROR HY000: Failed to open mysql.event
 ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
-ERROR HY000: Unknown event 'intact_check_1'
+ERROR HY000: Failed to open mysql.event
 ALTER EVENT intact_check_1 RENAME TO intact_check_2;
-ERROR HY000: Unknown event 'intact_check_1'
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check_1;
-ERROR HY000: Unknown event 'intact_check_1'
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check_2;
-ERROR HY000: Unknown event 'intact_check_2'
+ERROR HY000: Failed to open mysql.event
 DROP EVENT intact_check;
+ERROR HY000: Failed to open mysql.event
 DROP DATABASE IF EXISTS mysqltest_no_such_database;
 Warnings:
 Note	1008	Can't drop database 'mysqltest_no_such_database'; database doesn't exist
 CREATE DATABASE mysqltest_db2;
 DROP DATABASE mysqltest_db2;
+Warnings:
+Error	1545	Failed to open mysql.event
 SELECT @@event_scheduler;
 @@event_scheduler
 OFF
@@ -425,4 +435,42 @@ CREATE TABLE mysql.event like event_like
 DROP TABLE event_like;
 SHOW EVENTS;
 Db	Name	Definer	Time zone	Type	Execute at	Interval value	Interval field	Starts	Ends	Status	Originator	character_set_client	collation_connection	Database Collation
+
+#
+# Bug#12394306: the sever may crash if mysql.event is corrupted
+#
+
+CREATE EVENT ev1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
+ALTER EVENT ev1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
+
+CREATE TABLE event_original LIKE mysql.event;
+INSERT INTO event_original SELECT * FROM mysql.event;
+
+ALTER TABLE mysql.event MODIFY modified CHAR(1);
+Warnings:
+Warning	1265	Data truncated for column 'modified' at row 1
+
+SHOW EVENTS;
+ERROR HY000: Failed to open mysql.event
+
+SELECT event_name, created, last_altered FROM information_schema.events;
+ERROR HY000: Failed to open mysql.event
+
+CREATE EVENT ev2 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
+ERROR HY000: Failed to open mysql.event
+
+ALTER EVENT ev1 ON SCHEDULE EVERY 9 HOUR DO SELECT 9;
+ERROR HY000: Failed to open mysql.event
+
+DROP TABLE mysql.event;
+RENAME TABLE event_original TO mysql.event;
+
+DROP EVENT ev1;
+
+SHOW EVENTS;
+Db	Name	Definer	Time zone	Type	Execute at	Interval value	Interval field	Starts	Ends	Status	Originator	character_set_client	collation_connection	Database Collation
+
+# 
+# End of tests
+#
 drop database events_test;

=== modified file 'mysql-test/r/events_restart.result'
--- a/mysql-test/r/events_restart.result	2008-04-09 07:43:20 +0000
+++ b/mysql-test/r/events_restart.result	2011-05-04 12:59:24 +0000
@@ -1,3 +1,4 @@
+call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted");
 set global event_scheduler=off;
 drop database if exists events_test;
 create database events_test;
@@ -52,6 +53,8 @@ Warnings:
 Note	1008	Can't drop database 'mysqltest_database_not_exists'; database doesn't exist
 create database mysqltest_db1;
 drop database mysqltest_db1;
+Warnings:
+Error	1545	Failed to open mysql.event
 Restore the original mysql.event table
 drop table mysql.event;
 rename table event_like to mysql.event;

=== modified file 'mysql-test/t/events_1.test'
--- a/mysql-test/t/events_1.test	2008-02-22 20:28:59 +0000
+++ b/mysql-test/t/events_1.test	2011-05-04 12:59:24 +0000
@@ -4,6 +4,8 @@
 # Can't test with embedded server that doesn't support grants
 -- source include/not_embedded.inc
 
+call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted");
+
 --disable_warnings
 drop database if exists events_test;
 drop database if exists db_x;
@@ -270,23 +272,28 @@ SHOW EVENTS;
 --echo Try to alter mysql.event: the server should fail to load
 --echo event information after mysql.event was tampered with.
 --echo 
---echo First, let's add a column to the end and make sure everything
---echo works as before
+--echo First, let's add a column to the end and check the error is emitted.
 --echo 
 ALTER TABLE mysql.event ADD dummy INT;
---replace_column 8 # 9 #
+--error ER_EVENT_OPEN_TABLE_FAILED
 SHOW EVENTS;
+--error ER_EVENT_OPEN_TABLE_FAILED
 SELECT event_name FROM INFORMATION_SCHEMA.events;
---replace_regex /STARTS '[^']+'/STARTS '#'/
+--error ER_EVENT_OPEN_TABLE_FAILED
 SHOW CREATE EVENT intact_check;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT no_such_event;
+--error ER_EVENT_OPEN_TABLE_FAILED
 CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
+--error ER_EVENT_OPEN_TABLE_FAILED
 ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
+--error ER_EVENT_OPEN_TABLE_FAILED
 ALTER EVENT intact_check_1 RENAME TO intact_check_2;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check_1;
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check_2;
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check;
 DROP DATABASE IF EXISTS mysqltest_no_such_database;
 CREATE DATABASE mysqltest_db2;
@@ -296,6 +303,7 @@ SHOW VARIABLES LIKE 'event_scheduler';
 SET GLOBAL event_scheduler=OFF;
 # Clean up
 ALTER TABLE mysql.event DROP dummy;
+DROP EVENT intact_check;
 CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
 --echo 
 --echo Now let's add a column to the first position: the server
@@ -303,24 +311,26 @@ CREATE EVENT intact_check ON SCHEDULE EV
 --echo 
 ALTER TABLE mysql.event ADD dummy INT FIRST;
 --error ER_CANNOT_LOAD_FROM_TABLE
+--error ER_EVENT_OPEN_TABLE_FAILED
 SHOW EVENTS;
 --error ER_CANNOT_LOAD_FROM_TABLE
+--error ER_EVENT_OPEN_TABLE_FAILED
 SELECT event_name FROM INFORMATION_SCHEMA.events;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 SHOW CREATE EVENT intact_check;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT no_such_event;
---error ER_EVENT_STORE_FAILED
+--error ER_EVENT_OPEN_TABLE_FAILED
 CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 ALTER EVENT intact_check_1 RENAME TO intact_check_2;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check_1;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check_2;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check;
 # Should work OK
 DROP DATABASE IF EXISTS mysqltest_no_such_database;
@@ -341,25 +351,25 @@ INSERT INTO event_like SELECT * FROM mys
 --echo
 --echo 
 ALTER TABLE mysql.event DROP comment, DROP starts;
---error ER_CANNOT_LOAD_FROM_TABLE
+--error ER_EVENT_OPEN_TABLE_FAILED
 SHOW EVENTS;
---error ER_CANNOT_LOAD_FROM_TABLE
+--error ER_EVENT_OPEN_TABLE_FAILED
 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
---error ER_CANNOT_LOAD_FROM_TABLE
+--error ER_EVENT_OPEN_TABLE_FAILED
 SHOW CREATE EVENT intact_check;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT no_such_event;
---error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
+--error ER_EVENT_OPEN_TABLE_FAILED
 CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 ALTER EVENT intact_check_1 RENAME TO intact_check_2;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check_1;
---error ER_EVENT_DOES_NOT_EXIST
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check_2;
-# Should succeed
+--error ER_EVENT_OPEN_TABLE_FAILED
 DROP EVENT intact_check;
 DROP DATABASE IF EXISTS mysqltest_no_such_database;
 CREATE DATABASE mysqltest_db2;
@@ -407,9 +417,54 @@ CREATE TABLE mysql.event like event_like
 DROP TABLE event_like;
 --replace_column 8 # 9 #
 SHOW EVENTS;
-# 
-# End of tests
-#
+
+--echo
+--echo #
+--echo # Bug#12394306: the sever may crash if mysql.event is corrupted
+--echo #
+
+--echo
+CREATE EVENT ev1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
+ALTER EVENT ev1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
+
+--echo
+CREATE TABLE event_original LIKE mysql.event;
+INSERT INTO event_original SELECT * FROM mysql.event;
+
+--echo
+ALTER TABLE mysql.event MODIFY modified CHAR(1);
+
+--echo
+--error ER_EVENT_OPEN_TABLE_FAILED
+SHOW EVENTS;
+
+--echo
+--error ER_EVENT_OPEN_TABLE_FAILED
+SELECT event_name, created, last_altered FROM information_schema.events;
+
+--echo
+--error ER_EVENT_OPEN_TABLE_FAILED
+CREATE EVENT ev2 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
+
+--echo
+--error ER_EVENT_OPEN_TABLE_FAILED
+ALTER EVENT ev1 ON SCHEDULE EVERY 9 HOUR DO SELECT 9;
+
+--echo
+DROP TABLE mysql.event;
+RENAME TABLE event_original TO mysql.event;
+
+--echo
+DROP EVENT ev1;
+
+--echo
+SHOW EVENTS;
+
+
+--echo
+--echo # 
+--echo # End of tests
+--echo #
 
 let $wait_condition=
   select count(*) = 0 from information_schema.processlist

=== modified file 'mysql-test/t/events_restart.test'
--- a/mysql-test/t/events_restart.test	2008-04-09 07:43:20 +0000
+++ b/mysql-test/t/events_restart.test	2011-05-04 12:59:24 +0000
@@ -1,6 +1,8 @@
 # Can't test with embedded server that doesn't support grants
 -- source include/not_embedded.inc
 
+call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted");
+
 #
 # Test that when the server is restarted, it checks mysql.event table,
 # and disables the scheduler if it's not up to date.

=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc	2011-03-21 16:02:47 +0000
+++ b/sql/event_db_repository.cc	2011-05-04 12:59:24 +0000
@@ -582,6 +582,14 @@ Event_db_repository::open_event_table(TH
 
   *table= tables.table;
   tables.table->use_all_columns();
+
+  if (table_intact.check(*table, &event_table_def))
+  {
+    close_thread_tables(thd);
+    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
   DBUG_RETURN(FALSE);
 }
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1 branch (alexander.nozdrin:3680 to 3681) Bug#12394306Alexander Nozdrin4 May