From: Alexander Barkov Date: January 28 2011 11:50am Subject: bzr commit into mysql-5.1 branch (alexander.barkov:3565) Bug#58036 List-Archive: http://lists.mysql.com/commits/129849 X-Bug: 58036 Message-Id: <201101281150.p0SBoKwf004589@bar.myoffice.izhnet.ru> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============4186934839779356073==" --===============4186934839779356073== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/bar/mysql-bzr/mysql-5.1.b58036/ based on revid:anders.song@stripped 3565 Alexander Barkov 2011-01-28 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/mysql_priv.h - introducing a new function, to reuse in all places where we need to check client character set. - changing return type for thd_init_client_charset() to bool, to return errors to the caller @ sql/set_var.cc Using new function. @ sql/sql_connect.cc - in case of unsupported client character set send error and return true - moving thd->update_charset() inside thd_init_client_charset(), as they are always called in pair. - in case of success return false @ sql/sql_parse.cc - moving thd_init_client_charset() before check_user(), because DBUG_ASSERT forbids calling my_error() after check_user() has authenticated the user and has done my_ok(). - removing thd->update_charset(), as it's now done in thd_init_client_charset(). @ tests/mysql_client_test.c Adding test modified: sql/mysql_priv.h sql/set_var.cc sql/sql_connect.cc sql/sql_parse.cc tests/mysql_client_test.c === modified file 'sql/mysql_priv.h' --- a/sql/mysql_priv.h 2011-01-15 05:51:41 +0000 +++ b/sql/mysql_priv.h 2011-01-28 11:28:05 +0000 @@ -1019,7 +1019,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 mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); @@ -2536,6 +2536,10 @@ bool load_collation(MEM_ROOT *mem_root, CHARSET_INFO *dflt_cl, CHARSET_INFO **cl); +inline bool charset_is_good_for_parser(CHARSET_INFO *cs) +{ return test(cs->mbminlen == 1); } + + #endif /* MYSQL_SERVER */ extern "C" int test_if_data_home_dir(const char *dir); === modified file 'sql/set_var.cc' --- a/sql/set_var.cc 2010-12-28 23:47:05 +0000 +++ b/sql/set_var.cc 2011-01-28 11:28:05 +0000 @@ -2187,7 +2187,7 @@ bool sys_var_character_set_client::check if (sys_var_character_set_sv::check(thd, var)) return 1; /* Currently, UCS-2 cannot be used as a client character set */ - if (var->save_result.charset->mbminlen > 1) + if (!charset_is_good_for_parser(var->save_result.charset)) { my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, var->save_result.charset->csname); === modified file 'sql/sql_connect.cc' --- a/sql/sql_connect.cc 2010-11-11 07:34:14 +0000 +++ b/sql/sql_connect.cc 2011-01-28 11:28:05 +0000 @@ -582,8 +582,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 @@ -592,10 +607,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; @@ -606,10 +621,19 @@ void thd_init_client_charset(THD *thd, u } else { + if (!charset_is_good_for_parser(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; } + thd->update_charset(); + return false; } @@ -782,8 +806,8 @@ static int check_connection(THD *thd) thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16; thd->max_client_packet_length= uint4korr(net->read_pos+4); DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8])); - thd_init_client_charset(thd, (uint) net->read_pos[8]); - thd->update_charset(); + if (thd_init_client_charset(thd, (uint) net->read_pos[8])) + return 1; end= (char*) net->read_pos+32; } else === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2011-01-15 05:51:41 +0000 +++ b/sql/sql_parse.cc 2011-01-28 11:28:05 +0000 @@ -1183,8 +1183,18 @@ bool dispatch_command(enum enum_server_c /* Clear variables that are allocated */ thd->user_connect= 0; thd->security_ctx->priv_user= thd->security_ctx->user; + if (cs_number) + { + if (thd_init_client_charset(thd, cs_number)) + { + res= true; + goto com_change_user_finalize; + } + } res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); +com_change_user_finalize: + if (res) { x_free(thd->security_ctx->user); @@ -1202,12 +1212,6 @@ bool dispatch_command(enum enum_server_c #endif /* NO_EMBEDDED_ACCESS_CHECKS */ x_free(save_db); x_free(save_security_ctx.user); - - if (cs_number) - { - thd_init_client_charset(thd, cs_number); - thd->update_charset(); - } } break; } === modified file 'tests/mysql_client_test.c' --- a/tests/mysql_client_test.c 2010-12-28 23:47:05 +0000 +++ b/tests/mysql_client_test.c 2011-01-28 11:28:05 +0000 @@ -18399,6 +18399,71 @@ 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; +} + +/* Read and parse arguments and MySQL options from my.cnf */ @@ -18724,6 +18789,7 @@ static struct my_tests_st my_tests[]= { { "test_bug42373", test_bug42373 }, { "test_bug54041", test_bug54041 }, { "test_bug47485", test_bug47485 }, + { "test_bug58036", test_bug58036 }, { 0, 0 } }; --===============4186934839779356073== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/alexander.barkov@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: alexander.barkov@stripped\ # 2qev2hg0gs3h73lm # target_branch: file:///home/bar/mysql-bzr/mysql-5.1.b58036/ # testament_sha1: 1362a70515d524c39cdf8e04ab0f334dc354f684 # timestamp: 2011-01-28 14:50:20 +0300 # base_revision_id: anders.song@stripped\ # 2i1k6vlf6gs0qdpy # # Begin bundle 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 Sf8XckU4UJBkKzG5 --===============4186934839779356073==--