From 8e65618fa975e92d115479d40fce332ba4cd126c Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 14 Oct 2009 16:26:16 +0500 Subject: [PATCH 1/5] BUG#47455 - The myisam_crash_before_flush_keys test fails on Windows Simplified and made more determenistic myisam_crash_before_flush_keys test. mysql-test/r/myisam_crash_before_flush_keys.result: We don't need myisamchk to test this bug fix. CHECK TABLE after server restart is enough to ensure that the fix works. mysql-test/t/myisam_crash_before_flush_keys.test: We don't need myisamchk to test this bug fix. CHECK TABLE after server restart is enough to ensure that the fix works. --- .../r/myisam_crash_before_flush_keys.result | 28 ++++--------------- .../t/myisam_crash_before_flush_keys.test | 12 ++------ 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/mysql-test/r/myisam_crash_before_flush_keys.result b/mysql-test/r/myisam_crash_before_flush_keys.result index 372f2e41590..d3545ea47d0 100644 --- a/mysql-test/r/myisam_crash_before_flush_keys.result +++ b/mysql-test/r/myisam_crash_before_flush_keys.result @@ -15,31 +15,13 @@ SET SESSION debug="d,crash_before_flush_keys"; # Run the crashing query FLUSH TABLE t1; ERROR HY000: Lost connection to MySQL server during query -# Run MYISAMCHK tool to check the table t1 and repair -myisamchk: MyISAM file MYSQLD_DATADIR/test/t1 -myisamchk: warning: 1 client is using or hasn't closed the table properly -myisamchk: error: Size of indexfile is: 1024 Should be: 3072 -MYISAMCHK: Unknown error 126 -myisamchk: error: Can't read indexpage from filepos: 1024 -MyISAM-table 'MYSQLD_DATADIR/test/t1' is corrupted -Fix it using switch "-r" or "-o" # Write file to make mysql-test-run.pl start the server # Turn on reconnect # Call script that will poll the server waiting for # it to be back online again -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) NOT NULL DEFAULT '0', - `b` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`a`,`b`), - KEY `b` (`b`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 -SELECT * FROM t1 FORCE INDEX (PRIMARY); -a b -1 2 -2 3 -3 4 -4 5 -5 6 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check warning 1 client is using or hasn't closed the table properly +test.t1 check error Size of indexfile is: 1024 Should be: 3072 +test.t1 check error Corrupt DROP TABLE t1; diff --git a/mysql-test/t/myisam_crash_before_flush_keys.test b/mysql-test/t/myisam_crash_before_flush_keys.test index d6559f7760d..1860ddd27e3 100644 --- a/mysql-test/t/myisam_crash_before_flush_keys.test +++ b/mysql-test/t/myisam_crash_before_flush_keys.test @@ -26,12 +26,6 @@ SET SESSION debug="d,crash_before_flush_keys"; --error 2013 FLUSH TABLE t1; ---echo # Run MYISAMCHK tool to check the table t1 and repair ---replace_result $MYISAMCHK MYISAMCHK $MYSQLD_DATADIR MYSQLD_DATADIR ---error 255 ---exec $MYISAMCHK -cs $MYSQLD_DATADIR/test/t1 2>&1 ---exec $MYISAMCHK -rs $MYSQLD_DATADIR/test/t1 - --echo # Write file to make mysql-test-run.pl start the server --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect @@ -42,8 +36,6 @@ FLUSH TABLE t1; --echo # it to be back online again --source include/wait_until_connected_again.inc -SHOW CREATE TABLE t1; - -SELECT * FROM t1 FORCE INDEX (PRIMARY); - +# Must report that the table wasn't closed properly +CHECK TABLE t1; DROP TABLE t1; From 834ba32293173639880423839bbd245c601c0d50 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Mon, 19 Oct 2009 09:43:33 +0200 Subject: [PATCH 2/5] Bug#47627 SET @@{global.session}.local_variable in stored routine causes crash Adding @@session and @@global prefixes to a declared variable in a stored procedure the server would lead to a crash. The reason was that during the parsing of the syntactic rule 'option_value' an uninitialized set_var object was pushed to the parameter stack of the SET statement. The parent rule 'option_type_value' interpreted the existence of variables on the parameter stack as an assignment and wrapped it in a sp_instr_set object. As the procedure later was executed an attempt was made to run the method 'check()' on an uninitialized member object (NULL value) belonging to the previously created but uninitialized object. sql/sql_yacc.yy: * Assign the option_type at once since it is needed by the next parsing rule (internal_variable_name) * Rearranged the if statement to reduce negations and gain more clarity of code. * Added check for option_type to better detect if current variable is a SP local variable or a system variable. --- mysql-test/r/sp.result | 45 +++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 46 ++++++++++++++++++++++++++++++- sql/sql_yacc.yy | 61 ++++++++++++++++++++++++++++++++---------- 3 files changed, 137 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 67514c314f4..752edf8db41 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6979,6 +6979,51 @@ CALL p1; ERROR 42S22: Unknown column 'A.b' in 'IN/ALL/ANY subquery' DROP PROCEDURE p1; DROP TABLE t1, t2; +# +# Bug47627 SET @@{global.session}.local_variable in stored routine causes crash +# +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +CREATE PROCEDURE p1() +BEGIN +DECLARE v INT DEFAULT 0; +SET @@session.v= 10; +END// +ERROR HY000: Unknown system variable 'v' +CREATE PROCEDURE p2() +BEGIN +DECLARE v INT DEFAULT 0; +SET v= 10; +END// +call p2()// +CREATE PROCEDURE p3() +BEGIN +DECLARE v INT DEFAULT 0; +SELECT @@session.v; +END// +ERROR HY000: Unknown system variable 'v' +CREATE PROCEDURE p4() +BEGIN +DECLARE v INT DEFAULT 0; +SET @@global.v= 10; +END// +ERROR HY000: Unknown system variable 'v' +CREATE PROCEDURE p5() +BEGIN +DECLARE v INT DEFAULT 0; +SET @@global.query_cache_size= 0; +SET @@session.identity= 1; +SELECT @@session.identity; +SELECT @@global.query_cache_size; +END// +CALL p5(); +@@session.identity +1 +@@global.query_cache_size +0 +DROP PROCEDURE p2; +DROP PROCEDURE p5; # ------------------------------------------------------------------ # -- End of 5.1 tests # ------------------------------------------------------------------ diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 44c4556340e..328dde4b26f 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -8263,7 +8263,51 @@ CALL p1; DROP PROCEDURE p1; DROP TABLE t1, t2; - +--echo # +--echo # Bug47627 SET @@{global.session}.local_variable in stored routine causes crash +--echo # +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +--enable_warnings +delimiter //; +--error ER_UNKNOWN_SYSTEM_VARIABLE +CREATE PROCEDURE p1() +BEGIN + DECLARE v INT DEFAULT 0; + SET @@session.v= 10; +END// +CREATE PROCEDURE p2() +BEGIN + DECLARE v INT DEFAULT 0; + SET v= 10; +END// +call p2()// +--error ER_UNKNOWN_SYSTEM_VARIABLE +CREATE PROCEDURE p3() +BEGIN + DECLARE v INT DEFAULT 0; + SELECT @@session.v; +END// +--error ER_UNKNOWN_SYSTEM_VARIABLE +CREATE PROCEDURE p4() +BEGIN + DECLARE v INT DEFAULT 0; + SET @@global.v= 10; +END// +CREATE PROCEDURE p5() +BEGIN + DECLARE v INT DEFAULT 0; + SET @@global.query_cache_size= 0; + SET @@session.identity= 1; + SELECT @@session.identity; + SELECT @@global.query_cache_size; +END// +delimiter ;// +CALL p5(); +DROP PROCEDURE p2; +DROP PROCEDURE p5; --echo # ------------------------------------------------------------------ --echo # -- End of 5.1 tests --echo # ------------------------------------------------------------------ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 12e124230e5..ceebde4f7b3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -11783,8 +11783,17 @@ option_type: ; option_type2: - /* empty */ { $$= OPT_DEFAULT; } - | ONE_SHOT_SYM { Lex->one_shot_set= 1; $$= OPT_SESSION; } + /* empty */ + { + $$= OPT_DEFAULT; + Lex->option_type= OPT_DEFAULT; + } + | ONE_SHOT_SYM + { + Lex->one_shot_set= 1; + $$= OPT_SESSION; + Lex->option_type= OPT_SESSION; + } ; opt_var_type: @@ -11795,10 +11804,26 @@ opt_var_type: ; opt_var_ident_type: - /* empty */ { $$=OPT_DEFAULT; } - | GLOBAL_SYM '.' { $$=OPT_GLOBAL; } - | LOCAL_SYM '.' { $$=OPT_SESSION; } - | SESSION_SYM '.' { $$=OPT_SESSION; } + /* empty */ + { + $$=OPT_DEFAULT; + Lex->option_type= OPT_DEFAULT; + } + | GLOBAL_SYM '.' + { + $$=OPT_GLOBAL; + Lex->option_type= OPT_GLOBAL; + } + | LOCAL_SYM '.' + { + $$=OPT_SESSION; + Lex->option_type= OPT_SESSION; + } + | SESSION_SYM '.' + { + $$=OPT_SESSION; + Lex->option_type= OPT_SESSION; + } ; ext_option_value: @@ -12038,8 +12063,22 @@ internal_variable_name: sp_pcontext *spc= lex->spcont; sp_variable_t *spv; - /* We have to lookup here since local vars can shadow sysvars */ - if (!spc || !(spv = spc->find_variable(&$1))) + /* + We have to lookup here since local vars can shadow sysvars. + + We also have to inspect the option_type first since the variable + identifier might have been prefixed with @@session or @@global + prefixes. Without this check we would wrongly identify them + as SP local variables. + */ + if (lex->option_type == OPT_DEFAULT && spc && + (spv= spc->find_variable(&$1))) + { + /* An SP local variable */ + $$.var= NULL; + $$.base_name= $1; + } + else { /* Not an SP local variable */ sys_var *tmp=find_sys_var(thd, $1.str, $1.length); @@ -12056,12 +12095,6 @@ internal_variable_name: lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; } } - else - { - /* An SP local variable */ - $$.var= NULL; - $$.base_name= $1; - } } | ident '.' ident { From 52db2f3646846f3d02526ec53be891c998b75fac Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Oct 2009 13:16:09 +0800 Subject: [PATCH 3/5] Bug #34777 mysqlbinlog: --help output for --base64-output is hard to understand There are some problems about help text: - It is stated that "auto" is the default twice. It need be stated only once. - It is stated that --base64-output is short for --base64-output=always. But that sounds like the default is "always", not "auto". Make the help text clear as following: Determine when the output statements should be base64-encoded BINLOG statements: 'never' disables it and works only for binlogs without row-based events; 'auto' prints base64 only when necessary (i.e., for row-based events and format description events); 'always' prints base64 whenever possible. 'always' is for debugging only and should not be used in a production system. If this argument is not given, the default is 'auto'; if it is given with no argument, 'always' is used. --- client/mysqlbinlog.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index ebe34231238..4652b27639b 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -992,13 +992,11 @@ static struct my_option my_long_options[] = /* 'unspec' is not mentioned because it is just a placeholder. */ "Determine when the output statements should be base64-encoded BINLOG " "statements: 'never' disables it and works only for binlogs without " - "row-based events; 'auto' is the default and prints base64 only when " - "necessary (i.e., for row-based events and format description events); " - "'decode-rows' suppresses BINLOG statements for row events, but does " - "not exit as an error if a row event is found, unlike 'never'; " - "'always' prints base64 whenever possible. 'always' is for debugging " - "only and should not be used in a production system. The default is " - "'auto'. --base64-output is a short form for --base64-output=always." + "row-based events; 'auto' prints base64 only when necessary (i.e., " + "for row-based events and format description events); 'always' prints " + "base64 whenever possible. 'always' is for debugging only and should " + "not be used in a production system. If this argument is not given, " + "the default is 'auto'; if it is given with no argument, 'always' is used." ,(uchar**) &opt_base64_output_mode_str, (uchar**) &opt_base64_output_mode_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, From 882535423de244036c8d26b055aeaf292d3abaf7 Mon Sep 17 00:00:00 2001 From: Satya B Date: Tue, 20 Oct 2009 11:47:57 +0530 Subject: [PATCH 4/5] Fix for Bug #41597 - After rename of user, there are additional grants when grants are reapplied. After renaming a user and trying to re-apply grants results in additional grants. This is because we use username as part of the key for GRANT_TABLE structure. When the user is renamed, we only change the username stored and the hash key still contains the old user name and this results in the extra privileges Fixed by rebuilding the hash key and updating the column_priv_hash structure when the user is renamed mysql-test/r/grant3.result: Bug #41597 - After rename of user, there are additional grants when grants are reapplied. Testcase for BUG#41597 mysql-test/t/grant3.test: Bug #41597 - After rename of user, there are additional grants when grants are reapplied. Testcase for BUG#41597 sql/sql_acl.cc: Bug #41597 - After rename of user, there are additional grants when grants are reapplied. Fixed handle_grant_struct() to update the hash key when the user is renamed. Added to set_user_details() method to GRANT_NAME class --- mysql-test/r/grant3.result | 38 +++++++++++++++++++++++++++++++ mysql-test/t/grant3.test | 35 +++++++++++++++++++++++++++++ sql/sql_acl.cc | 46 ++++++++++++++++++++++++++++---------- 3 files changed, 107 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/grant3.result b/mysql-test/r/grant3.result index f38848111ad..59c64ee84ae 100644 --- a/mysql-test/r/grant3.result +++ b/mysql-test/r/grant3.result @@ -154,4 +154,42 @@ SELECT * FROM mysqltest_1.t1; a DROP USER 'mysqltest1'@'%'; DROP DATABASE mysqltest_1; +# +# Bug#41597 - After rename of user, there are additional grants +# when grants are reapplied. +# +CREATE DATABASE temp; +CREATE TABLE temp.t1(a INT, b VARCHAR(10)); +INSERT INTO temp.t1 VALUES(1, 'name1'); +INSERT INTO temp.t1 VALUES(2, 'name2'); +INSERT INTO temp.t1 VALUES(3, 'name3'); +CREATE USER 'user1'@'%'; +RENAME USER 'user1'@'%' TO 'user2'@'%'; +# Show privileges after rename and BEFORE grant +SHOW GRANTS FOR 'user2'@'%'; +Grants for user2@% +GRANT USAGE ON *.* TO 'user2'@'%' +GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%'; +# Show privileges after rename and grant +SHOW GRANTS FOR 'user2'@'%'; +Grants for user2@% +GRANT USAGE ON *.* TO 'user2'@'%' +GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%' +# Connect as the renamed user +SHOW GRANTS; +Grants for user2@% +GRANT USAGE ON *.* TO 'user2'@'%' +GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%' +SELECT a FROM temp.t1; +a +1 +2 +3 +# Check for additional privileges by accessing a +# non privileged column. We shouldn't be able to +# access this column. +SELECT b FROM temp.t1; +ERROR 42000: SELECT command denied to user 'user2'@'localhost' for column 'b' in table 't1' +DROP USER 'user2'@'%'; +DROP DATABASE temp; End of 5.0 tests diff --git a/mysql-test/t/grant3.test b/mysql-test/t/grant3.test index 9a635048774..437fc9a278f 100644 --- a/mysql-test/t/grant3.test +++ b/mysql-test/t/grant3.test @@ -163,6 +163,41 @@ connection default; DROP USER 'mysqltest1'@'%'; DROP DATABASE mysqltest_1; +--echo # +--echo # Bug#41597 - After rename of user, there are additional grants +--echo # when grants are reapplied. +--echo # + +CREATE DATABASE temp; +CREATE TABLE temp.t1(a INT, b VARCHAR(10)); +INSERT INTO temp.t1 VALUES(1, 'name1'); +INSERT INTO temp.t1 VALUES(2, 'name2'); +INSERT INTO temp.t1 VALUES(3, 'name3'); + + +CREATE USER 'user1'@'%'; +RENAME USER 'user1'@'%' TO 'user2'@'%'; +--echo # Show privileges after rename and BEFORE grant +SHOW GRANTS FOR 'user2'@'%'; +GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%'; +--echo # Show privileges after rename and grant +SHOW GRANTS FOR 'user2'@'%'; + +--echo # Connect as the renamed user +connect (conn1, localhost, user2,,); +connection conn1; +SHOW GRANTS; +SELECT a FROM temp.t1; +--echo # Check for additional privileges by accessing a +--echo # non privileged column. We shouldn't be able to +--echo # access this column. +--error ER_COLUMNACCESS_DENIED_ERROR +SELECT b FROM temp.t1; +disconnect conn1; + +connection default; +DROP USER 'user2'@'%'; +DROP DATABASE temp; --echo End of 5.0 tests diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ea17a4227ef..8f1e2c70fe6 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2096,6 +2096,8 @@ public: GRANT_NAME (TABLE *form); virtual ~GRANT_NAME() {}; virtual bool ok() { return privs != 0; } + void set_user_details(const char *h, const char *d, + const char *u, const char *t); }; @@ -2113,27 +2115,36 @@ public: }; - -GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u, - const char *t, ulong p) - :privs(p) +void GRANT_NAME::set_user_details(const char *h, const char *d, + const char *u, const char *t) { /* Host given by user */ update_hostname(&host, strdup_root(&memex, h)); - db = strdup_root(&memex,d); + if (db != d) + { + db= strdup_root(&memex, d); + if (lower_case_table_names) + my_casedn_str(files_charset_info, db); + } user = strdup_root(&memex,u); sort= get_sort(3,host.hostname,db,user); - tname= strdup_root(&memex,t); - if (lower_case_table_names) + if (tname != t) { - my_casedn_str(files_charset_info, db); - my_casedn_str(files_charset_info, tname); + tname= strdup_root(&memex, t); + if (lower_case_table_names) + my_casedn_str(files_charset_info, tname); } key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; hash_key = (char*) alloc_root(&memex,key_length); strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); } +GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u, + const char *t, ulong p) + :db(0), tname(0), privs(p) +{ + set_user_details(h, d, u, t); +} GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, const char *t, ulong p, ulong c) @@ -5183,9 +5194,20 @@ static int handle_grant_struct(uint struct_no, bool drop, case 2: case 3: - grant_name->user= strdup_root(&mem, user_to->user.str); - update_hostname(&grant_name->host, - strdup_root(&mem, user_to->host.str)); + /* + Update the grant structure with the new user name and + host name + */ + grant_name->set_user_details(user_to->host.str, grant_name->db, + user_to->user.str, grant_name->tname); + + /* + Since username is part of the hash key, when the user name + is renamed, the hash key is changed. Update the hash to + ensure that the position matches the new hash key value + */ + hash_update(&column_priv_hash, (byte *)grant_name, + grant_name->hash_key, grant_name->key_length); break; } } From c12dad02d6014a497fec4a61f3c1df39fa9ca7f2 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 20 Oct 2009 12:47:00 +0500 Subject: [PATCH 5/5] A post fix for BUG#45645 Mysql server close all connection and restart using lower function - Initialized caseinfo only if it is NULL --- strings/ctype-uca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 9fb18c0c472..6ae0cc3a293 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -7858,7 +7858,8 @@ static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(size_t)) return 1; } - cs->caseinfo= my_unicase_default; + if (!cs->caseinfo) + cs->caseinfo= my_unicase_default; if (!(newweights= (uint16**) (*alloc)(256*sizeof(uint16*)))) return 1;