Description:
Interactive 'connect' command was not able to take
a database name as argument, if it contained special
characters, such as a space in it's name.
How to repeat:
mysql> use `stupid db` localhost
Suggested fix:
Here is a patch of mysql.cc from version 13.2 to 13.3
*** /my/tmp/mysql.cc Wed Dec 25 21:21:56 2002
--- client/mysql.cc Wed Dec 25 23:52:53 2002
***************
*** 40,46 ****
#include <signal.h>
#include <violite.h>
! const char *VER= "13.2";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
--- 40,46 ----
#include <signal.h>
#include <violite.h>
! const char *VER= "13.3";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
***************
*** 195,201 ****
static int init_tee(char *);
static void end_tee();
static const char* construct_prompt();
! static char *get_arg(char *line);
static void init_username();
static void add_int_to_prompt(int toadd);
--- 195,201 ----
static int init_tee(char *);
static void end_tee();
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);
***************
*** 2231,2253 ****
static int
com_connect(String *buffer, char *line)
{
! char *tmp,buff[256];
bool save_rehash= rehash;
int error;
if (buffer)
{
! while (my_isspace(system_charset_info,*line))
! line++;
! strnmov(buff,line,sizeof(buff)-1); // Don't destroy history! if (buff[0] == '\\') // Short command
! buff[1]=' ';
! tmp=(char *) strtok(buff," \t"); // Skip connect command
! if (tmp && (tmp=(char *) strtok(NullS," \t;")))
! {
! my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
! current_db=my_strdup(tmp,MYF(MY_WME));
! if ((tmp=(char *) strtok(NullS," \t;")))
{
my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
current_host=my_strdup(tmp,MYF(MY_WME));
--- 2231,2251 ----
static int
com_connect(String *buffer, char *line)
{
! char *tmp, buff[256];
bool save_rehash= rehash;
int error;
+ bzero(buff, sizeof(buff));
if (buffer)
{
! strmov(buff, line);
! tmp= get_arg(buff, 0);
! if (tmp && *tmp)
! {
! my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
! current_db= my_strdup(tmp, MYF(MY_WME));
! tmp= get_arg(buff, 1);
! if (tmp)
{
my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
current_host=my_strdup(tmp,MYF(MY_WME));
***************
*** 2333,2340 ****
char *tmp;
char buff[256];
strmov(buff, line);
! tmp= get_arg(buff);
if (!tmp || !*tmp)
{
put_info("USE must be followed by a database name", INFO_ERROR);
--- 2331,2339 ----
char *tmp;
char buff[256];
+ bzero(buff, sizeof(buff));
strmov(buff, line);
! tmp= get_arg(buff, 0);
if (!tmp || !*tmp)
{
put_info("USE must be followed by a database name", INFO_ERROR);
***************
*** 2376,2384 ****
}
enum quote_type { NO_QUOTE, SQUOTE, DQUOTE, BTICK };
! char *get_arg(char *line)
{
char *ptr;
my_bool quoted= 0, valid_arg= 0;
--- 2375,2394 ----
}
+
+ /*
+ Gets argument from a command on the command line. If get_next_arg is
+ not defined, skips the command and returns the first argument. The
+ line is modified by adding zero to the end of the argument. If
+ get_next_arg is defined, then the function searches for end of string
+ first, after found, returns the next argument and adds zero to the
+ end. If you ever wish to use this feature, remember to initialize all
+ items in the array to zero first.
+ */
+
enum quote_type { NO_QUOTE, SQUOTE, DQUOTE, BTICK };
! char *get_arg(char *line, my_bool get_next_arg)
{
char *ptr;
my_bool quoted= 0, valid_arg= 0;
***************
*** 2386,2398 ****
enum quote_type qtype= NO_QUOTE;
ptr= line;
! /* skip leading white spaces */
! while (my_isspace(system_charset_info, *ptr))
! ptr++;
! if (*ptr == '\\') // short command was used
! ptr+= 2;
! while (!my_isspace(system_charset_info, *ptr)) // skip command
! ptr++;
while (my_isspace(system_charset_info, *ptr))
ptr++;
if ((*ptr == '\'' && (qtype= SQUOTE)) ||
--- 2396,2417 ----
enum quote_type qtype= NO_QUOTE;
ptr= line;
! if (get_next_arg)
! {
! for (; ptr && *ptr; ptr++);
! if ((ptr + 1) && *(ptr + 1))
! ptr++;
! }
! else
! {
! /* skip leading white spaces */
! while (my_isspace(system_charset_info, *ptr))
! ptr++;
! if (*ptr == '\\') // short command was used
! ptr+= 2;
! while (!my_isspace(system_charset_info, *ptr)) // skip command
! ptr++;
! }
while (my_isspace(system_charset_info, *ptr))
ptr++;
if ((*ptr == '\'' && (qtype= SQUOTE)) ||
***************
*** 2415,2423 ****
ptr= line;
ptr+= count;
}
! else if (!quoted && *ptr == ' ')
! *(ptr + 1) = 0;
! else if ((*ptr == '\'' && qtype == SQUOTE) ||
(*ptr == '\"' && qtype == DQUOTE) ||
(*ptr == '`' && qtype == BTICK))
{
--- 2434,2441 ----
ptr= line;
ptr+= count;
}
! else if ((!quoted && *ptr == ' ') ||
! (*ptr == '\'' && qtype == SQUOTE) ||
(*ptr == '\"' && qtype == DQUOTE) ||
(*ptr == '`' && qtype == BTICK))
{
Description: Interactive 'connect' command was not able to take a database name as argument, if it contained special characters, such as a space in it's name. How to repeat: mysql> use `stupid db` localhost Suggested fix: Here is a patch of mysql.cc from version 13.2 to 13.3 *** /my/tmp/mysql.cc Wed Dec 25 21:21:56 2002 --- client/mysql.cc Wed Dec 25 23:52:53 2002 *************** *** 40,46 **** #include <signal.h> #include <violite.h> ! const char *VER= "13.2"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 --- 40,46 ---- #include <signal.h> #include <violite.h> ! const char *VER= "13.3"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 *************** *** 195,201 **** static int init_tee(char *); static void end_tee(); static const char* construct_prompt(); ! static char *get_arg(char *line); static void init_username(); static void add_int_to_prompt(int toadd); --- 195,201 ---- static int init_tee(char *); static void end_tee(); 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); *************** *** 2231,2253 **** static int com_connect(String *buffer, char *line) { ! char *tmp,buff[256]; bool save_rehash= rehash; int error; if (buffer) { ! while (my_isspace(system_charset_info,*line)) ! line++; ! strnmov(buff,line,sizeof(buff)-1); // Don't destroy history! if (buff[0] == '\\') // Short command ! buff[1]=' '; ! tmp=(char *) strtok(buff," \t"); // Skip connect command ! if (tmp && (tmp=(char *) strtok(NullS," \t;"))) ! { ! my_free(current_db,MYF(MY_ALLOW_ZERO_PTR)); ! current_db=my_strdup(tmp,MYF(MY_WME)); ! if ((tmp=(char *) strtok(NullS," \t;"))) { my_free(current_host,MYF(MY_ALLOW_ZERO_PTR)); current_host=my_strdup(tmp,MYF(MY_WME)); --- 2231,2251 ---- static int com_connect(String *buffer, char *line) { ! char *tmp, buff[256]; bool save_rehash= rehash; int error; + bzero(buff, sizeof(buff)); if (buffer) { ! strmov(buff, line); ! tmp= get_arg(buff, 0); ! if (tmp && *tmp) ! { ! my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); ! current_db= my_strdup(tmp, MYF(MY_WME)); ! tmp= get_arg(buff, 1); ! if (tmp) { my_free(current_host,MYF(MY_ALLOW_ZERO_PTR)); current_host=my_strdup(tmp,MYF(MY_WME)); *************** *** 2333,2340 **** char *tmp; char buff[256]; strmov(buff, line); ! tmp= get_arg(buff); if (!tmp || !*tmp) { put_info("USE must be followed by a database name", INFO_ERROR); --- 2331,2339 ---- char *tmp; char buff[256]; + bzero(buff, sizeof(buff)); strmov(buff, line); ! tmp= get_arg(buff, 0); if (!tmp || !*tmp) { put_info("USE must be followed by a database name", INFO_ERROR); *************** *** 2376,2384 **** } enum quote_type { NO_QUOTE, SQUOTE, DQUOTE, BTICK }; ! char *get_arg(char *line) { char *ptr; my_bool quoted= 0, valid_arg= 0; --- 2375,2394 ---- } + + /* + Gets argument from a command on the command line. If get_next_arg is + not defined, skips the command and returns the first argument. The + line is modified by adding zero to the end of the argument. If + get_next_arg is defined, then the function searches for end of string + first, after found, returns the next argument and adds zero to the + end. If you ever wish to use this feature, remember to initialize all + items in the array to zero first. + */ + enum quote_type { NO_QUOTE, SQUOTE, DQUOTE, BTICK }; ! char *get_arg(char *line, my_bool get_next_arg) { char *ptr; my_bool quoted= 0, valid_arg= 0; *************** *** 2386,2398 **** enum quote_type qtype= NO_QUOTE; ptr= line; ! /* skip leading white spaces */ ! while (my_isspace(system_charset_info, *ptr)) ! ptr++; ! if (*ptr == '\\') // short command was used ! ptr+= 2; ! while (!my_isspace(system_charset_info, *ptr)) // skip command ! ptr++; while (my_isspace(system_charset_info, *ptr)) ptr++; if ((*ptr == '\'' && (qtype= SQUOTE)) || --- 2396,2417 ---- enum quote_type qtype= NO_QUOTE; ptr= line; ! if (get_next_arg) ! { ! for (; ptr && *ptr; ptr++); ! if ((ptr + 1) && *(ptr + 1)) ! ptr++; ! } ! else ! { ! /* skip leading white spaces */ ! while (my_isspace(system_charset_info, *ptr)) ! ptr++; ! if (*ptr == '\\') // short command was used ! ptr+= 2; ! while (!my_isspace(system_charset_info, *ptr)) // skip command ! ptr++; ! } while (my_isspace(system_charset_info, *ptr)) ptr++; if ((*ptr == '\'' && (qtype= SQUOTE)) || *************** *** 2415,2423 **** ptr= line; ptr+= count; } ! else if (!quoted && *ptr == ' ') ! *(ptr + 1) = 0; ! else if ((*ptr == '\'' && qtype == SQUOTE) || (*ptr == '\"' && qtype == DQUOTE) || (*ptr == '`' && qtype == BTICK)) { --- 2434,2441 ---- ptr= line; ptr+= count; } ! else if ((!quoted && *ptr == ' ') || ! (*ptr == '\'' && qtype == SQUOTE) || (*ptr == '\"' && qtype == DQUOTE) || (*ptr == '`' && qtype == BTICK)) {