From a22c3d21096f827d4eb7dfc1b3546cb758123756 Mon Sep 17 00:00:00 2001
From: unknown <tnurnberg@mysql.com/white.intern.koehntopp.de>
Date: Sun, 24 Feb 2008 13:58:07 +0100
Subject: [PATCH] Bug#32753: PAD_CHAR_TO_FULL_LENGTH is not documented and
 interferes with grant tables

SQL-mode PAD_CHAR_TO_FULL_LENGTH affected mysqld's user-table too. If
enabled, user-name and host were space-padded and no longer matched
the login-data of incoming connexions.

Patch disregards pad-flag while loading privileges so ability to log
in does not depend on SQL-mode.


mysql-test/r/sql_mode.result:
  show that SQL-mode 'PAD_CHAR_TO_FULL_LENGTH' does not affect
  loading of privileges (and by extension, ability to log in).
mysql-test/t/sql_mode.test:
  show that SQL-mode 'PAD_CHAR_TO_FULL_LENGTH' does not affect
  loading of privileges (and by extension, ability to log in).
sql/sql_acl.cc:
  temporarily disable SQL-mode 'PAD_CHAR_TO_FULL_LENGTH' while
  reloading privileges
---
 mysql-test/r/sql_mode.result | 10 ++++++++++
 mysql-test/t/sql_mode.test   | 29 +++++++++++++++++++++++++++++
 sql/sql_acl.cc               | 15 ++++++++++++---
 3 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 2b34ff8c02..401340f204 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -496,3 +496,13 @@ xb	x
 xcx
 drop table t1;
 SET @@SQL_MODE=@OLD_SQL_MODE;
+create user mysqltest_32753@localhost;
+set @OLD_SQL_MODE=@@SESSION.SQL_MODE;
+set session sql_mode='PAD_CHAR_TO_FULL_LENGTH';
+flush privileges;
+select current_user();
+current_user()
+mysqltest_32753@localhost
+set session sql_mode=@OLD_SQL_MODE;
+flush privileges;
+drop user mysqltest_32753@localhost;
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index 7a9036c862..acc9cc7979 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -279,3 +279,32 @@ select concat('x',b,'x') from t1;
 drop table t1;
 
 SET @@SQL_MODE=@OLD_SQL_MODE;
+
+
+#
+# Bug #32753: PAD_CHAR_TO_FULL_LENGTH is not documented and interferes
+#             with grant tables
+#
+
+create user mysqltest_32753@localhost;
+
+# try to make the user-table space-padded
+--connection default
+set @OLD_SQL_MODE=@@SESSION.SQL_MODE;
+set session sql_mode='PAD_CHAR_TO_FULL_LENGTH';
+flush privileges;
+
+# if user-table is affected by PAD_CHAR_TO_FULL_LENGTH, our connect will fail
+# --error 1045
+connect (user_32753,localhost,mysqltest_32753,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+select current_user();
+
+# clean up
+--connection default
+set session sql_mode=@OLD_SQL_MODE;
+flush privileges;
+
+--disconnect user_32753
+
+--connection default
+drop user mysqltest_32753@localhost;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 064aa6dc04..abeacd49c1 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -192,7 +192,7 @@ static void update_hostname(acl_host_and_ip *host, const char *hostname);
 static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
 			     const char *ip);
 static my_bool acl_load(THD *thd, TABLE_LIST *tables);
-static my_bool grant_load(TABLE_LIST *tables);
+static my_bool grant_load(THD *thd, TABLE_LIST *tables);
 
 /*
   Convert scrambled password to binary form, according to scramble type, 
@@ -314,8 +314,11 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
   bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE;
   char tmp_name[NAME_LEN+1];
   int password_length;
+  ulong old_sql_mode= thd->variables.sql_mode;
   DBUG_ENTER("acl_load");
 
+  thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
+
   grant_version++; /* Privileges updated */
 
   acl_cache->clear(1);				// Clear locked hostname cache
@@ -622,6 +625,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
   return_val=0;
 
 end:
+  thd->variables.sql_mode= old_sql_mode;
   DBUG_RETURN(return_val);
 }
 
@@ -3613,7 +3617,7 @@ end_unlock:
     @retval TRUE Error
 */
 
-static my_bool grant_load(TABLE_LIST *tables)
+static my_bool grant_load(THD *thd, TABLE_LIST *tables)
 {
   MEM_ROOT *memex_ptr;
   my_bool return_val= 1;
@@ -3621,7 +3625,11 @@ static my_bool grant_load(TABLE_LIST *tables)
   bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE;
   MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,
                                                            THR_MALLOC);
+  ulong old_sql_mode= thd->variables.sql_mode;
   DBUG_ENTER("grant_load");
+
+  thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
+
   (void) hash_init(&column_priv_hash,system_charset_info,
                    0,0,0, (hash_get_key) get_grant_table,
                    (hash_free_key) free_grant_table,0);
@@ -3673,6 +3681,7 @@ static my_bool grant_load(TABLE_LIST *tables)
   return_val=0;					// Return ok
 
 end_unlock:
+  thd->variables.sql_mode= old_sql_mode;
   t_table->file->ha_index_end();
   my_pthread_setspecific_ptr(THR_MALLOC, save_mem_root_ptr);
   DBUG_RETURN(return_val);
@@ -3786,7 +3795,7 @@ my_bool grant_reload(THD *thd)
   old_mem= memex;
   init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0);
 
-  if ((return_val= grant_load(tables)))
+  if ((return_val= grant_load(thd, tables)))
   {						// Error. Revert to old hash
     DBUG_PRINT("error",("Reverting to old privileges"));
     grant_free();				/* purecov: deadcode */
-- 
2.30.9