List:Commits« Previous MessageNext Message »
From:Jorgen Loland Date:November 11 2010 3:32pm
Subject:bzr commit into mysql-5.5-bugteam branch (jorgen.loland:3120) Bug#54812
View as plain text  
#At file:///export/home/jl208045/mysql/mysql-5.5-bugteam-54812/ based on revid:svoj@stripped

 3120 Jorgen Loland	2010-11-11
      Bug#54812: assert in Diagnostics_area::set_ok_status 
                 during EXPLAIN
      
      Before the patch, send_eof() of some subclasses of 
      select_result (e.g., select_send::send_eof()) could 
      handle being called after an error had occured while others 
      could not. The methods that were not well-behaved would trigger
      an ASSERT on debug builds. Release builds were not affected.
      
      Consider the following query as an example for how the ASSERT
      could be triggered:
      
      A user without execute privilege on f() does
         SELECT MAX(key1) INTO @dummy FROM t1 WHERE f() < 1;
      resulting in "ERROR 42000: execute command denied to user..." 
      
      The server would end the query by calling send_eof(). The 
      fact that the error had occured would make the ASSERT trigger. 
      
      select_dumpvar::send_eof() was the offending method in the
      bug report, but the problem also applied to other 
      subclasses of select_result. This patch uniforms send_eof() 
      of all subclasses of select_result to handle being called 
      after an error has occured. 
     @ mysql-test/r/not_embedded_server.result
        Added test for BUG#54812
     @ mysql-test/t/not_embedded_server.test
        Added test for BUG#54812
     @ sql/sql_class.cc
        Make send_eof() of all subclasses of select_result handle being
        called after an error has occured.
     @ sql/sql_insert.cc
        Make send_eof() of all subclasses of select_result handle being
        called after an error has occured.
     @ sql/sql_prepare.cc
        Make send_eof() of all subclasses of select_result handle being
        called after an error has occured.
     @ sql/sql_update.cc
        Make send_eof() of all subclasses of select_result handle being
        called after an error has occured.

    modified:
      mysql-test/r/not_embedded_server.result
      mysql-test/t/not_embedded_server.test
      sql/sql_class.cc
      sql/sql_insert.cc
      sql/sql_prepare.cc
      sql/sql_update.cc
=== modified file 'mysql-test/r/not_embedded_server.result'
--- a/mysql-test/r/not_embedded_server.result	2009-12-04 23:02:48 +0000
+++ b/mysql-test/r/not_embedded_server.result	2010-11-11 15:32:17 +0000
@@ -14,3 +14,32 @@ flush privileges;
 ERROR HY000: Table 'host' was not locked with LOCK TABLES
 unlock tables;
 drop table t1;
+#
+# Bug#54812: assert in Diagnostics_area::set_ok_status during EXPLAIN
+#
+CREATE USER nopriv_user@localhost;
+connection: default
+DROP TABLE IF EXISTS t1,t2,t3;
+DROP FUNCTION IF EXISTS f;
+CREATE TABLE t1 (key1 INT PRIMARY KEY);
+CREATE TABLE t2 (key2 INT);
+INSERT INTO t1 VALUES (1),(2);
+CREATE FUNCTION f() RETURNS INT RETURN 1;
+GRANT FILE ON *.* TO 'nopriv_user'@'localhost';
+FLUSH PRIVILEGES;
+connection: con1
+SELECT MAX(key1) FROM t1 WHERE f() < 1 INTO OUTFILE 'mytest';
+ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f'
+INSERT INTO t2 SELECT MAX(key1) FROM t1 WHERE f() < 1;
+ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f'
+SELECT MAX(key1) INTO @dummy FROM t1 WHERE f() < 1;
+ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f'
+CREATE TABLE t3 (i INT) AS SELECT MAX(key1) FROM t1 WHERE f() < 1;
+ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f'
+connection: default
+DROP TABLE t1,t2;
+DROP FUNCTION f;
+DROP USER nopriv_user@localhost;
+#
+# End Bug#54812
+#

=== modified file 'mysql-test/t/not_embedded_server.test'
--- a/mysql-test/t/not_embedded_server.test	2009-12-04 23:02:48 +0000
+++ b/mysql-test/t/not_embedded_server.test	2010-11-11 15:32:17 +0000
@@ -54,3 +54,57 @@ lock tables t1 read;
 flush privileges;
 unlock tables;
 drop table t1;
+
+--echo #
+--echo # Bug#54812: assert in Diagnostics_area::set_ok_status during EXPLAIN
+--echo #
+
+CREATE USER nopriv_user@localhost;
+
+connection default;
+--echo connection: default
+
+--disable_warnings
+DROP TABLE IF EXISTS t1,t2,t3;
+DROP FUNCTION IF EXISTS f;
+--enable_warnings
+
+CREATE TABLE t1 (key1 INT PRIMARY KEY);
+CREATE TABLE t2 (key2 INT);
+INSERT INTO t1 VALUES (1),(2);
+
+CREATE FUNCTION f() RETURNS INT RETURN 1;
+
+GRANT FILE ON *.* TO 'nopriv_user'@'localhost';
+
+FLUSH PRIVILEGES;
+
+connect (con1,localhost,nopriv_user,,);
+connection con1;
+--echo connection: con1
+
+--error ER_PROCACCESS_DENIED_ERROR
+SELECT MAX(key1) FROM t1 WHERE f() < 1 INTO OUTFILE 'mytest';
+
+--error ER_PROCACCESS_DENIED_ERROR
+INSERT INTO t2 SELECT MAX(key1) FROM t1 WHERE f() < 1;
+
+--error ER_PROCACCESS_DENIED_ERROR
+SELECT MAX(key1) INTO @dummy FROM t1 WHERE f() < 1;
+
+--error ER_PROCACCESS_DENIED_ERROR
+CREATE TABLE t3 (i INT) AS SELECT MAX(key1) FROM t1 WHERE f() < 1;
+
+disconnect con1;
+--source include/wait_until_disconnected.inc
+
+connection default;
+--echo connection: default
+
+DROP TABLE t1,t2;
+DROP FUNCTION f;
+DROP USER nopriv_user@localhost;
+
+--echo #
+--echo # End Bug#54812
+--echo #

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-10-23 13:09:27 +0000
+++ b/sql/sql_class.cc	2010-11-11 15:32:17 +0000
@@ -1841,6 +1841,13 @@ void select_to_file::send_error(uint err
 
 bool select_to_file::send_eof()
 {
+  /* 
+    Don't send EOF if we're in error condition (which implies we've already
+    sent or are sending an error)
+  */
+  if (thd->is_error())
+    return TRUE;
+
   int error= test(end_io_cache(&cache));
   if (mysql_file_close(file, MYF(MY_WME)))
     error= 1;
@@ -2881,6 +2888,13 @@ bool select_dumpvar::send_data(List<Item
 
 bool select_dumpvar::send_eof()
 {
+  /* 
+    Don't send EOF if we're in error condition (which implies we've already
+    sent or are sending an error)
+  */
+  if (thd->is_error())
+    return TRUE;
+
   if (! row_count)
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                  ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2010-10-07 10:01:51 +0000
+++ b/sql/sql_insert.cc	2010-11-11 15:32:17 +0000
@@ -3504,6 +3504,13 @@ bool select_insert::send_eof()
   DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
                        trans_table, table->file->table_type()));
 
+  /* 
+    Don't send EOF if we're in error condition (which implies we've already
+    sent or are sending an error)
+  */
+  if (thd->is_error())
+    DBUG_RETURN(TRUE);
+
   error= (thd->locked_tables_mode <= LTM_LOCK_TABLES ?
           table->file->ha_end_bulk_insert() : 0);
   table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
@@ -4047,6 +4054,13 @@ void select_create::send_error(uint errc
 
 bool select_create::send_eof()
 {
+  /* 
+    Don't send EOF if we're in error condition (which implies we've already
+    sent or are sending an error)
+  */
+  if (thd->is_error())
+    return TRUE;
+
   bool tmp=select_insert::send_eof();
   if (tmp)
     abort();

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2010-11-03 14:15:18 +0000
+++ b/sql/sql_prepare.cc	2010-11-11 15:32:17 +0000
@@ -2898,6 +2898,13 @@ bool Select_fetch_protocol_binary::send_
 
 bool Select_fetch_protocol_binary::send_eof()
 {
+  /* 
+    Don't send EOF if we're in error condition (which implies we've already
+    sent or are sending an error)
+  */
+  if (thd->is_error())
+    return TRUE;
+
   ::my_eof(thd);
   return FALSE;
 }

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2010-10-07 10:01:51 +0000
+++ b/sql/sql_update.cc	2010-11-11 15:32:17 +0000
@@ -2061,6 +2061,13 @@ bool multi_update::send_eof()
   thd_proc_info(thd, "updating reference tables");
 
   /* 
+    Don't send EOF if we're in error condition (which implies we've already
+    sent or are sending an error)
+  */
+  if (thd->is_error())
+    return TRUE;
+
+  /* 
      Does updates for the last n - 1 tables, returns 0 if ok;
      error takes into account killed status gained in do_updates()
   */


Attachment: [text/bzr-bundle] bzr/jorgen.loland@oracle.com-20101111153217-6yta8ab5c8ny0jm1.bundle
Thread
bzr commit into mysql-5.5-bugteam branch (jorgen.loland:3120) Bug#54812Jorgen Loland11 Nov