Bug mysql_real_connect() connects again if

given an already connected MYSQL handle

mysql_real_connect() did not check whether the MYSQL connection
handler was already connected and connected again even if so. 
Now a CR_ALREADY_CONNECTED error is returned.
This commit is contained in:
Magne Mahre 2009-10-09 14:30:54 +02:00
parent 10b43fcdcf
commit 63350dfc8b
5 changed files with 65 additions and 13 deletions
include
libmysql
libmysqld
sql-common
tests

View file

@ -97,6 +97,7 @@ extern const char *client_errors[]; /* Error messages */
#define CR_SERVER_LOST_EXTENDED 2055
#define CR_STMT_CLOSED 2056
#define CR_NEW_STMT_METADATA 2057
#define CR_ERROR_LAST /*Copy last error nr:*/ 2057
#define CR_ALREADY_CONNECTED 2058
#define CR_ERROR_LAST /*Copy last error nr:*/ 2058
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */

View file

@ -85,6 +85,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
"This handle is already connected. Use a separate handle for each connection."
""
};
@ -151,6 +152,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
"This handle is already connected. Use a separate handle for each connection."
""
};
@ -215,6 +217,7 @@ const char *client_errors[]=
"Lost connection to MySQL server at '%s', system error: %d",
"Statement closed indirectly because of a preceeding %s() call",
"The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again",
"This handle is already connected. Use a separate handle for each connection."
""
};
#endif

View file

@ -28,6 +28,7 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include <sql_common.h>
#include "client_settings.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
@ -77,17 +78,6 @@ static my_bool is_NT(void)
}
#endif
/**************************************************************************
** Shut down connection
**************************************************************************/
static void end_server(MYSQL *mysql)
{
DBUG_ENTER("end_server");
free_old_query(mysql);
DBUG_VOID_RETURN;
}
int mysql_init_character_set(MYSQL *mysql);
@ -104,6 +94,13 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
db ? db : "(Null)",
user ? user : "(Null)"));
/* Test whether we're already connected */
if (mysql->server_version)
{
set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate);
DBUG_RETURN(0);
}
if (!host || !host[0])
host= mysql->options.host;
@ -215,7 +212,7 @@ error:
{
/* Free alloced memory */
my_bool free_me=mysql->free_me;
end_server(mysql);
free_old_query(mysql);
mysql->free_me=0;
mysql_close(mysql);
mysql->free_me=free_me;

View file

@ -1919,6 +1919,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
db ? db : "(Null)",
user ? user : "(Null)"));
/* Test whether we're already connected */
if (net->vio)
{
set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate);
DBUG_RETURN(0);
}
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
mysql->methods= &client_methods;

View file

@ -18026,6 +18026,49 @@ static void test_bug44495()
DBUG_VOID_RETURN;
}
/**
Bug# 33831 mysql_real_connect() should fail if
given an already connected MYSQL handle.
*/
static void test_bug33831(void)
{
MYSQL *l_mysql;
my_bool error;
DBUG_ENTER("test_bug33831");
error= 0;
if (!(l_mysql= mysql_init(NULL)))
{
myerror("mysql_init() failed");
DIE_UNLESS(0);
}
if (!(mysql_real_connect(l_mysql, opt_host, opt_user,
opt_password, current_db, opt_port,
opt_unix_socket, 0)))
{
myerror("connection failed");
DIE_UNLESS(0);
}
if (mysql_real_connect(l_mysql, opt_host, opt_user,
opt_password, current_db, opt_port,
opt_unix_socket, 0))
{
myerror("connection should have failed");
DIE_UNLESS(0);
}
mysql_close(l_mysql);
DBUG_VOID_RETURN;
}
/*
Read and parse arguments and MySQL options from my.cnf
*/
@ -18336,6 +18379,7 @@ static struct my_tests_st my_tests[]= {
{ "test_wl4166_1", test_wl4166_1 },
{ "test_wl4166_2", test_wl4166_2 },
{ "test_bug38486", test_bug38486 },
{ "test_bug33831", test_bug33831 },
{ "test_bug40365", test_bug40365 },
{ "test_bug43560", test_bug43560 },
#ifdef HAVE_QUERY_CACHE