From 8a96012922865ecd1d87290869f6a54e74d3ee12 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 18 Feb 2011 16:12:36 +0300 Subject: Bug#11765108 (Bug#58036) client utf32, utf16, ucs2 should be disallowed, they crash server A separate fix for 5.1 (as 5.1 and 5.5 have seriously differged in the related pieces of the code). A patch for 5.5 was approved earlier. 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/sql_priv.h - changing return type for thd_init_client_charset() to bool, to return errors to the caller @ sql/sql_var.cc - using new function @ sql/sql_connect.cc - thd_client_charset_init: in case of unsupported client character set send error and return true; in case of success return false - check_connection: Return error if character set initialization failed @ sql/sql_parse.cc - check charset in the very beginnig of the CMD_CHANGE_USER handling code @ tests/mysql_client_test.c - adding tests --- tests/mysql_client_test.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'tests') diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 80c7be64e94..5a45c132a5f 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -18398,6 +18398,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; +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -18724,6 +18790,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 } }; -- cgit v1.2.1 From cd3a8131c63b47be027ea8cbcdec42324679eb08 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 18 Feb 2011 17:17:37 +0300 Subject: A post-fix for b58036. --- tests/mysql_client_test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 5a45c132a5f..fc1f2e8293e 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -18417,7 +18417,7 @@ static void test_bug58036() if (!opt_silent) printf("mysql_real_connect() succeeded (failure expected)\n"); mysql_close(conn); - DIE(); + DIE(""); } if (!opt_silent) @@ -18443,7 +18443,7 @@ static void test_bug58036() printf("mysql_real_connect() failed: %s (%d)\n", mysql_error(conn), mysql_errno(conn)); mysql_close(conn); - DIE(); + DIE(""); } mysql_options(conn, MYSQL_SET_CHARSET_NAME, "ucs2"); @@ -18452,7 +18452,7 @@ static void test_bug58036() if (!opt_silent) printf("mysql_change_user() succedded, error expected!"); mysql_close(conn); - DIE(); + DIE(""); } if (!opt_silent) -- cgit v1.2.1 From 6c2f5e306ca3fa621cd25cedd49181d6e0d5cbc6 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Tue, 15 Mar 2011 17:36:12 +0600 Subject: Fixed Bug#11764168 "56976: SEVERE DENIAL OF SERVICE IN PREPARED STATEMENTS". The problem was that server didn't check resulting size of prepared statement argument which was set using mysql_send_long_data() API. By calling mysql_send_long_data() several times it was possible to create overly big string and thus force server to allocate memory for it. There was no way to limit this allocation. The solution is to add check for size of result string against value of max_long_data_size start-up parameter. When intermediate string exceeds max_long_data_size value an appropriate error message is emitted. We can't use existing max_allowed_packet parameter for this purpose since its value is limited by 1GB and therefore using it as a limit for data set through mysql_send_long_data() API would have been an incompatible change. Newly introduced max_long_data_size parameter gets value from max_allowed_packet parameter unless its value is specified explicitly. This new parameter is marked as deprecated and will be eventually replaced by max_allowed_packet parameter. Value of max_long_data_size parameter can be set only at server startup. --- tests/mysql_client_test.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'tests') diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index fc1f2e8293e..2e78c846fbc 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -18464,6 +18464,56 @@ static void test_bug58036() } +/* + Bug #56976: Severe Denial Of Service in prepared statements +*/ +static void test_bug56976() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + int rc; + const char* query = "SELECT LENGTH(?)"; + char *long_buffer; + unsigned long i, packet_len = 256 * 1024L; + unsigned long dos_len = 2 * 1024 * 1024L; + + DBUG_ENTER("test_bug56976"); + myheader("test_bug56976"); + + stmt= mysql_stmt_init(mysql); + check_stmt(stmt); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + memset(bind, 0, sizeof(bind)); + bind[0].buffer_type = MYSQL_TYPE_TINY_BLOB; + + rc= mysql_stmt_bind_param(stmt, bind); + check_execute(stmt, rc); + + long_buffer= (char*) my_malloc(packet_len, MYF(0)); + DIE_UNLESS(long_buffer); + + memset(long_buffer, 'a', packet_len); + + for (i= 0; i < dos_len / packet_len; i++) + { + rc= mysql_stmt_send_long_data(stmt, 0, long_buffer, packet_len); + check_execute(stmt, rc); + } + + my_free(long_buffer, MYF(0)); + rc= mysql_stmt_execute(stmt); + + DIE_UNLESS(rc && mysql_stmt_errno(stmt) == ER_UNKNOWN_ERROR); + + mysql_stmt_close(stmt); + + DBUG_VOID_RETURN; +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -18791,6 +18841,7 @@ static struct my_tests_st my_tests[]= { { "test_bug54041", test_bug54041 }, { "test_bug47485", test_bug47485 }, { "test_bug58036", test_bug58036 }, + { "test_bug56976", test_bug56976 }, { 0, 0 } }; -- cgit v1.2.1