List:Commits« Previous MessageNext Message »
From:Dmitry Shulga Date:September 7 2010 8:53am
Subject:bzr commit into mysql-5.1-bugteam branch (Dmitry.Shulga:3501) Bug#55421
View as plain text  
#At file:///Users/shulga/projects/mysql/5.1-bugteam-bug55421/ based on revid:martin.hansson@stripped

 3501 Dmitry Shulga	2010-09-07
      Fixed bug #55421 - Protocol::end_statement(): Assertion `0' on
      multi-table UPDATE IGNORE.
      The problem was that if there was an active SELECT statement
      during trigger execution, an error risen during the execution
      may cause a crash. The fix is to temporary reset LEX::current_select
      before trigger execution and restore it afterwards. This way
      errors risen during the trigger execution are processed as
      if there was no active SELECT.
     @ mysql-test/r/trigger_notembedded.result
        added test case result for bug #55421.
     @ mysql-test/t/trigger_notembedded.test
        added test case for bug #55421.
     @ sql/sql_trigger.cc
        Reset thd->lex->current_select before start trigger execution
        and restore its original value after execution is finished.
        This is neccessery in order to set error status in 
        diagnostic_area in case of trigger execution failure.

    modified:
      mysql-test/r/trigger_notembedded.result
      mysql-test/t/trigger_notembedded.test
      sql/sql_trigger.cc
=== modified file 'mysql-test/r/trigger_notembedded.result'
--- a/mysql-test/r/trigger_notembedded.result	2009-09-17 11:33:23 +0000
+++ b/mysql-test/r/trigger_notembedded.result	2010-09-07 08:53:46 +0000
@@ -474,4 +474,25 @@ SHOW CREATE TRIGGER db1.trg;
 ERROR 42000: Access denied; you need the TRIGGER privilege for this operation
 DROP USER 'no_rights'@'localhost';
 DROP DATABASE db1;
+DROP DATABASE IF EXISTS mysqltest_db1;
+CREATE DATABASE mysqltest_db1;
+USE mysqltest_db1;
+GRANT ALL ON mysqltest_db1.* TO mysqltest_u1@localhost;
+CREATE TABLE t1 (
+a1 int,
+a2 int
+);
+INSERT INTO t1 VALUES (1, 20);
+CREATE TRIGGER mysqltest_db1.upd_t1
+BEFORE UPDATE ON t1 FOR EACH ROW SET new.a2 = 200;
+CREATE TABLE t2 (
+a1 int
+);
+INSERT INTO t2 VALUES (2);
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+UPDATE IGNORE t1, t2 SET t1.a1 = 2, t2.a1 = 3 WHERE t1.a1 = 1 AND t2.a1 = 2;
+ERROR 42000: TRIGGER command denied to user 'mysqltest_u1'@'localhost' for table 't1'
+DROP DATABASE mysqltest_db1;
+DROP USER mysqltest_u1@localhost;
+USE test;
 End of 5.1 tests.

=== modified file 'mysql-test/t/trigger_notembedded.test'
--- a/mysql-test/t/trigger_notembedded.test	2009-06-25 10:52:50 +0000
+++ b/mysql-test/t/trigger_notembedded.test	2010-09-07 08:53:46 +0000
@@ -932,4 +932,52 @@ disconnect con1;
 DROP USER 'no_rights'@'localhost';
 DROP DATABASE db1;
 
+#
+# Bug#55421 Protocol::end_statement(): Assertion `0' on multi-table UPDATE IGNORE
+# To reproduce a crash we need to provoke a trigger execution with
+# the following conditions:
+#   - active SELECT statement during trigger execution
+#    (i.e. LEX::current_select != NULL);
+#   - IGNORE option (i.e. LEX::current_select->no_error == TRUE);
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_db1;
+--enable_warnings
+
+CREATE DATABASE mysqltest_db1;
+USE mysqltest_db1;
+
+GRANT ALL ON mysqltest_db1.* TO mysqltest_u1@localhost;
+
+--connect(con1,localhost,mysqltest_u1,,mysqltest_db1)
+
+CREATE TABLE t1 (
+  a1 int,
+  a2 int
+);
+INSERT INTO t1 VALUES (1, 20);
+
+CREATE TRIGGER mysqltest_db1.upd_t1
+BEFORE UPDATE ON t1 FOR EACH ROW SET new.a2 = 200;
+
+CREATE TABLE t2 (
+  a1 int
+);
+
+INSERT INTO t2 VALUES (2);
+
+--connection default
+
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
+
+--error ER_TABLEACCESS_DENIED_ERROR
+UPDATE IGNORE t1, t2 SET t1.a1 = 2, t2.a1 = 3 WHERE t1.a1 = 1 AND t2.a1 = 2;
+# Cleanup
+
+DROP DATABASE mysqltest_db1;
+DROP USER mysqltest_u1@localhost;
+
+--disconnect con1
+--connection default
+USE test;
+
 --echo End of 5.1 tests.

=== modified file 'sql/sql_trigger.cc'
--- a/sql/sql_trigger.cc	2010-06-11 12:52:06 +0000
+++ b/sql/sql_trigger.cc	2010-09-07 08:53:46 +0000
@@ -1989,6 +1989,7 @@ bool Table_triggers_list::process_trigge
   bool err_status;
   Sub_statement_state statement_state;
   sp_head *sp_trigger= bodies[event][time_type];
+  SELECT_LEX *save_current_select;
 
   if (sp_trigger == NULL)
     return FALSE;
@@ -2012,11 +2013,19 @@ bool Table_triggers_list::process_trigge
 
   thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
 
+  /*
+    Reset current_select before call execute_trigger() and
+    restore it after return from one. This way error is set
+    in case of failure during trigger execution.
+  */
+  save_current_select= thd->lex->current_select;
+  thd->lex->current_select= NULL;
   err_status=
     sp_trigger->execute_trigger(thd,
                                 &trigger_table->s->db,
                                 &trigger_table->s->table_name,
                                 &subject_table_grants[event][time_type]);
+  thd->lex->current_select= save_current_select;
 
   thd->restore_sub_statement_state(&statement_state);
 


Attachment: [text/bzr-bundle] bzr/dmitry.shulga@sun.com-20100907085346-lt8f2moerjiqegsv.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (Dmitry.Shulga:3501) Bug#55421Dmitry Shulga7 Sep