#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#54812 | Jorgen Loland | 11 Nov |