3342 Alexander Barkov 2011-02-18
Bug#11765108 (Bug#58036) client utf32, utf16, ucs2 should be disallowed, they crash server
Problem: ucs2 was correctly disallowed in "SET NAMES" only,
while mysql_real_connect() and mysql_change_user() still allowed
to use ucs2, which made server crash.
Fix: disallow ucs2 in mysql_real_connect() and mysql_change_user().
@ sql/set_var.cc
Using new function.
@ sql/sql_acl.cc
- Return error if character set initialization failed
- Getting rid of pointer aliasing:
Initialize user_name to NULL, to avoid double free().
@ sql/sql_connect.cc
- in case of unsupported client character set send error and return true
- in case of success return false
@ sql/sql_connect.h
- changing return type for thd_init_client_charset() to bool,
to return errors to the caller
@ sql/sql_parse.h
- introducing a new function, to reuse in all places where we need
to check client character set.
@ tests/mysql_client_test.c
Adding test
modified:
sql/set_var.cc
sql/sql_acl.cc
sql/sql_connect.cc
sql/sql_connect.h
sql/sql_parse.h
tests/mysql_client_test.c
3341 Alexander Barkov 2011-02-18
Bug#60101 COALESCE with cp1251 tables causes [Err] 1267 - Illegal mix of collations
Problem:
IF() did not copy collation derivation and repertoire from
an argument if the opposite argument was NULL:
IF(cond, res1, NULL)
IF(cond, NULL, res2)
only CHARSET_INFO pointer was copied.
This resulted in illegal mix of collations error.
Fix:
copy all collation parameters from the non-NULL argument:
CHARSET_INFO pointer, derivation, repertoire.
modified:
mysql-test/r/ctype_cp1251.result
mysql-test/t/ctype_cp1251.test
sql/item_cmpfunc.cc
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2011-02-17 11:53:09 +0000
+++ b/sql/set_var.cc 2011-02-18 09:46:55 +0000
@@ -776,7 +776,7 @@ int set_var_password::update(THD *thd)
int set_var_collation_client::check(THD *thd)
{
/* Currently, UCS-2 cannot be used as a client character set */
- if (character_set_client->mbminlen > 1)
+ if (!is_supported_parser_charset(character_set_client))
{
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
character_set_client->csname);
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2011-01-14 15:48:11 +0000
+++ b/sql/sql_acl.cc 2011-02-18 09:46:55 +0000
@@ -7799,7 +7799,8 @@ public:
Thd_charset_adapter(THD *thd_arg) : thd (thd_arg) {}
bool init_client_charset(uint cs_number)
{
- thd_init_client_charset(thd, cs_number);
+ if (thd_init_client_charset(thd, cs_number))
+ return true;
thd->update_charset();
return thd->is_error();
}
@@ -8929,9 +8930,8 @@ server_mpvio_initialize(THD *thd, MPVIO_
mpvio->auth_info.host_or_ip= thd->security_ctx->host_or_ip;
mpvio->auth_info.host_or_ip_length=
(unsigned int) strlen(thd->security_ctx->host_or_ip);
- mpvio->auth_info.user_name= thd->security_ctx->user;
- mpvio->auth_info.user_name_length= thd->security_ctx->user ?
- (unsigned int) strlen(thd->security_ctx->user) : 0;
+ mpvio->auth_info.user_name= NULL;
+ mpvio->auth_info.user_name_length= 0;
mpvio->connect_errors= connect_errors;
mpvio->status= MPVIO_EXT::FAILURE;
=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc 2010-12-15 22:59:21 +0000
+++ b/sql/sql_connect.cc 2011-02-18 09:46:55 +0000
@@ -370,8 +370,23 @@ void reset_mqh(LEX_USER *lu, bool get_th
}
-void thd_init_client_charset(THD *thd, uint cs_number)
+/**
+ Set thread character set variables from the given ID
+
+ @param thd thread handle
+ @param cs_number character set and collation ID
+
+ @retval 0 OK; character_set_client, collation_connection and
+ character_set_results are set to the new value,
+ or to the default global values.
+
+ @retval 1 error, e.g. the given ID is not supported by parser.
+ Corresponding SQL error is sent.
+*/
+
+bool thd_init_client_charset(THD *thd, uint cs_number)
{
+ CHARSET_INFO *cs;
/*
Use server character set and collation if
- opt_character_set_client_handshake is not set
@@ -380,10 +395,10 @@ void thd_init_client_charset(THD *thd, u
- client character set doesn't exists in server
*/
if (!opt_character_set_client_handshake ||
- !(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
+ !(cs= get_charset(cs_number, MYF(0))) ||
!my_strcasecmp(&my_charset_latin1,
global_system_variables.character_set_client->name,
- thd->variables.character_set_client->name))
+ cs->name))
{
thd->variables.character_set_client=
global_system_variables.character_set_client;
@@ -394,10 +409,18 @@ void thd_init_client_charset(THD *thd, u
}
else
{
+ if (!is_supported_parser_charset(cs))
+ {
+ /* Disallow non-supported parser character sets: UCS2, UTF16, UTF32 */
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
+ cs->csname);
+ return true;
+ }
thd->variables.character_set_results=
thd->variables.collation_connection=
- thd->variables.character_set_client;
+ thd->variables.character_set_client= cs;
}
+ return false;
}
=== modified file 'sql/sql_connect.h'
--- a/sql/sql_connect.h 2010-09-20 14:17:32 +0000
+++ b/sql/sql_connect.h 2011-02-18 09:46:55 +0000
@@ -33,7 +33,7 @@ void reset_mqh(LEX_USER *lu, bool get_th
bool check_mqh(THD *thd, uint check_command);
void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
void decrease_user_connections(USER_CONN *uc);
-void thd_init_client_charset(THD *thd, uint cs_number);
+bool thd_init_client_charset(THD *thd, uint cs_number);
bool setup_connection_thread_globals(THD *thd);
int check_user(THD *thd, enum enum_server_command command,
=== modified file 'sql/sql_parse.h'
--- a/sql/sql_parse.h 2010-08-31 09:59:51 +0000
+++ b/sql/sql_parse.h 2011-02-18 09:46:55 +0000
@@ -197,4 +197,10 @@ check_table_access(THD *thd, ulong requi
bool check_global_access(THD *thd, ulong want_access);
+inline bool is_supported_parser_charset(CHARSET_INFO *cs)
+{
+ return test(cs->mbminlen == 1);
+}
+
+
#endif /* SQL_PARSE_INCLUDED */
=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c 2010-12-29 00:26:31 +0000
+++ b/tests/mysql_client_test.c 2011-02-18 09:46:55 +0000
@@ -19289,6 +19289,72 @@ static void test_bug47485()
/*
+ Bug#58036 client utf32, utf16, ucs2 should be disallowed, they crash server
+*/
+static void test_bug58036()
+{
+ MYSQL *conn;
+ DBUG_ENTER("test_bug47485");
+ myheader("test_bug58036");
+
+ /* Part1: try to connect with ucs2 client character set */
+ conn= mysql_client_init(NULL);
+ mysql_options(conn, MYSQL_SET_CHARSET_NAME, "ucs2");
+ if (mysql_real_connect(conn, opt_host, opt_user,
+ opt_password, opt_db ? opt_db : "test",
+ opt_port, opt_unix_socket, 0))
+ {
+ if (!opt_silent)
+ printf("mysql_real_connect() succeeded (failure expected)\n");
+ mysql_close(conn);
+ DIE();
+ }
+
+ if (!opt_silent)
+ printf("Got mysql_real_connect() error (expected): %s (%d)\n",
+ mysql_error(conn), mysql_errno(conn));
+ DIE_UNLESS(mysql_errno(conn) == ER_WRONG_VALUE_FOR_VAR);
+ mysql_close(conn);
+
+
+ /*
+ Part2:
+ - connect with latin1
+ - then change client character set to ucs2
+ - then try mysql_change_user()
+ */
+ conn= mysql_client_init(NULL);
+ mysql_options(conn, MYSQL_SET_CHARSET_NAME, "latin1");
+ if (!mysql_real_connect(conn, opt_host, opt_user,
+ opt_password, opt_db ? opt_db : "test",
+ opt_port, opt_unix_socket, 0))
+ {
+ if (!opt_silent)
+ printf("mysql_real_connect() failed: %s (%d)\n",
+ mysql_error(conn), mysql_errno(conn));
+ mysql_close(conn);
+ DIE();
+ }
+
+ mysql_options(conn, MYSQL_SET_CHARSET_NAME, "ucs2");
+ if (!mysql_change_user(conn, opt_user, opt_password, NULL))
+ {
+ if (!opt_silent)
+ printf("mysql_change_user() succedded, error expected!");
+ mysql_close(conn);
+ DIE();
+ }
+
+ if (!opt_silent)
+ printf("Got mysql_change_user() error (expected): %s (%d)\n",
+ mysql_error(conn), mysql_errno(conn));
+ mysql_close(conn);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
Bug#49972: Crash in prepared statements.
The following case lead to a server crash:
@@ -19770,6 +19836,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug42373", test_bug42373 },
{ "test_bug54041", test_bug54041 },
{ "test_bug47485", test_bug47485 },
+ { "test_bug58036", test_bug58036 },
{ "test_bug57058", test_bug57058 },
{ 0, 0 }
};
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-5.5 branch (alexander.barkov:3341 to 3342) Bug#58036Bug#11765108 | Alexander Barkov | 18 Feb |