summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorNirbhay Choubey <nirbhay.choubey@oracle.com>2012-09-21 23:28:55 +0530
committerNirbhay Choubey <nirbhay.choubey@oracle.com>2012-09-21 23:28:55 +0530
commitf820334bbfd0cc6effdab7e947bb095885566a70 (patch)
tree3c6a54b44db1dfbd09c3170fc0899ce74ed2299d /client
parent373c428fbb4730bf2d1f6287b49d2aa5ef6ea362 (diff)
downloadmariadb-git-f820334bbfd0cc6effdab7e947bb095885566a70.tar.gz
Bug#14645196 MYSQL CLIENT'S USE COMMAND FAILS
WHEN DBNAME CONTAINS MULTIPLE QUOTES MySQL client's USE command might fail if the database name contains multiple quotes (backticks). The reason behind the failure being the method that client uses to remove/escape the quotes while parsing the USE command's option (dbname), where the option parsing might terminate if a matching quote is found. Also, C-APIs like mysql_select_db() expect a normalized dbname. Now, in certain cases, client might fail to normalize dbname similar to that of server and hence mysql_select_db() would fail. Fixed by getting the normalized dbname (indirectly) from the server by directly sending the "USE dbanme" as query to the server followed by a "SELECT DATABASE()". The above steps are only performed if number of quotes in the dbname is greater than 2. Once the normalized dbname is received, the original db is restored.
Diffstat (limited to 'client')
-rw-r--r--client/mysql.cc91
1 files changed, 89 insertions, 2 deletions
diff --git a/client/mysql.cc b/client/mysql.cc
index 3cb28e81164..965b1929af8 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -242,6 +242,8 @@ static const char* construct_prompt();
static char *get_arg(char *line, my_bool get_next_arg);
static void init_username();
static void add_int_to_prompt(int toadd);
+static int normalize_dbname(const char *line, char *buff, uint buff_size);
+static int get_quote_count(const char *line);
/* A structure which contains information on the commands this program
can understand. */
@@ -4112,8 +4114,23 @@ com_use(String *buffer __attribute__((unused)), char *line)
int select_db;
bzero(buff, sizeof(buff));
- strmake(buff, line, sizeof(buff) - 1);
- tmp= get_arg(buff, 0);
+
+ /*
+ In case number of quotes exceed 2, we try to get
+ the normalized db name.
+ */
+ if (get_quote_count(line) > 2)
+ {
+ if (normalize_dbname(line, buff, sizeof(buff)))
+ return put_error(&mysql);
+ tmp= buff;
+ }
+ else
+ {
+ strmake(buff, line, sizeof(buff) - 1);
+ tmp= get_arg(buff, 0);
+ }
+
if (!tmp || !*tmp)
{
put_info("USE must be followed by a database name", INFO_ERROR);
@@ -4179,6 +4196,62 @@ com_use(String *buffer __attribute__((unused)), char *line)
return 0;
}
+/**
+ Normalize database name.
+
+ @param line [IN] The command.
+ @param buff [OUT] Normalized db name.
+ @param buff_size [IN] Buffer size.
+
+ @return Operation status
+ @retval 0 Success
+ @retval 1 Failure
+
+ @note Sometimes server normilizes the database names
+ & APIs like mysql_select_db() expect normalized
+ database names. Since it is difficult to perform
+ the name conversion/normalization on the client
+ side, this function tries to get the normalized
+ dbname (indirectly) from the server.
+*/
+
+static int
+normalize_dbname(const char *line, char *buff, uint buff_size)
+{
+ MYSQL_RES *res= NULL;
+
+ /* Send the "USE db" commmand to the server. */
+ if (mysql_query(&mysql, line))
+ return 1;
+
+ /*
+ Now, get the normalized database name and store it
+ into the buff.
+ */
+ if (!mysql_query(&mysql, "SELECT DATABASE()") &&
+ (res= mysql_use_result(&mysql)))
+ {
+ MYSQL_ROW row= mysql_fetch_row(res);
+ if (row && row[0])
+ {
+ size_t len= strlen(row[0]);
+ /* Make sure there is enough room to store the dbname. */
+ if ((len > buff_size) || ! memcpy(buff, row[0], len))
+ {
+ mysql_free_result(res);
+ return 1;
+ }
+ }
+ mysql_free_result(res);
+ }
+
+ /* Restore the original database. */
+ if (current_db && mysql_select_db(&mysql, current_db))
+ return 1;
+
+ return 0;
+}
+
static int
com_warnings(String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
@@ -4258,6 +4331,20 @@ char *get_arg(char *line, my_bool get_next_arg)
return valid_arg ? start : NullS;
}
+/*
+ Number of quotes present in the command's argument.
+*/
+static int
+get_quote_count(const char *line)
+{
+ int quote_count;
+ const char *ptr= line;
+
+ for(quote_count= 0; ptr ++ && *ptr; ptr= strpbrk(ptr, "\"\'`"))
+ quote_count ++;
+
+ return quote_count;
+}
static int
sql_real_connect(char *host,char *database,char *user,char *password,