Skip to content

Commit 383007c

Browse files
committed
mysql cli: fix USE command quoting
* use proper sql quoting rules for USE, while preserving as much of historical behavior as possible * short commands (\u) behave as before
1 parent e4957de commit 383007c

File tree

3 files changed

+46
-26
lines changed

3 files changed

+46
-26
lines changed

client/mysql.cc

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ static void end_pager();
245245
static void init_tee(const char *);
246246
static void end_tee();
247247
static const char* construct_prompt();
248-
static char *get_arg(char *line, my_bool get_next_arg);
248+
enum get_arg_mode { CHECK, GET, GET_NEXT};
249+
static char *get_arg(char *line, get_arg_mode mode);
249250
static void init_username();
250251
static void add_int_to_prompt(int toadd);
251252
static int get_result_width(MYSQL_RES *res);
@@ -2223,7 +2224,7 @@ static COMMANDS *find_command(char *name)
22232224
if (!my_strnncoll(&my_charset_latin1, (uchar*) name, len,
22242225
(uchar*) commands[i].name, len) &&
22252226
(commands[i].name[len] == '\0') &&
2226-
(!end || commands[i].takes_params))
2227+
(!end || (commands[i].takes_params && get_arg(name, CHECK))))
22272228
{
22282229
index= i;
22292230
break;
@@ -3143,7 +3144,7 @@ com_charset(String *buffer __attribute__((unused)), char *line)
31433144
char buff[256], *param;
31443145
CHARSET_INFO * new_cs;
31453146
strmake_buf(buff, line);
3146-
param= get_arg(buff, 0);
3147+
param= get_arg(buff, GET);
31473148
if (!param || !*param)
31483149
{
31493150
return put_info("Usage: \\C charset_name | charset charset_name",
@@ -4228,12 +4229,12 @@ com_connect(String *buffer, char *line)
42284229
#ifdef EXTRA_DEBUG
42294230
tmp[1]= 0;
42304231
#endif
4231-
tmp= get_arg(buff, 0);
4232+
tmp= get_arg(buff, GET);
42324233
if (tmp && *tmp)
42334234
{
42344235
my_free(current_db);
42354236
current_db= my_strdup(tmp, MYF(MY_WME));
4236-
tmp= get_arg(buff, 1);
4237+
tmp= get_arg(buff, GET_NEXT);
42374238
if (tmp)
42384239
{
42394240
my_free(current_host);
@@ -4336,7 +4337,7 @@ com_delimiter(String *buffer __attribute__((unused)), char *line)
43364337
char buff[256], *tmp;
43374338

43384339
strmake_buf(buff, line);
4339-
tmp= get_arg(buff, 0);
4340+
tmp= get_arg(buff, GET);
43404341

43414342
if (!tmp || !*tmp)
43424343
{
@@ -4367,7 +4368,7 @@ com_use(String *buffer __attribute__((unused)), char *line)
43674368

43684369
bzero(buff, sizeof(buff));
43694370
strmake_buf(buff, line);
4370-
tmp= get_arg(buff, 0);
4371+
tmp= get_arg(buff, GET);
43714372
if (!tmp || !*tmp)
43724373
{
43734374
put_info("USE must be followed by a database name", INFO_ERROR);
@@ -4452,23 +4453,22 @@ com_nowarnings(String *buffer __attribute__((unused)),
44524453
}
44534454

44544455
/*
4455-
Gets argument from a command on the command line. If get_next_arg is
4456-
not defined, skips the command and returns the first argument. The
4457-
line is modified by adding zero to the end of the argument. If
4458-
get_next_arg is defined, then the function searches for end of string
4459-
first, after found, returns the next argument and adds zero to the
4460-
end. If you ever wish to use this feature, remember to initialize all
4461-
items in the array to zero first.
4456+
Gets argument from a command on the command line. If mode is not GET_NEXT,
4457+
skips the command and returns the first argument. The line is modified by
4458+
adding zero to the end of the argument. If mode is GET_NEXT, then the
4459+
function searches for end of string first, after found, returns the next
4460+
argument and adds zero to the end. If you ever wish to use this feature,
4461+
remember to initialize all items in the array to zero first.
44624462
*/
44634463

4464-
char *get_arg(char *line, my_bool get_next_arg)
4464+
static char *get_arg(char *line, get_arg_mode mode)
44654465
{
44664466
char *ptr, *start;
4467-
my_bool quoted= 0, valid_arg= 0;
4467+
bool short_cmd= false;
44684468
char qtype= 0;
44694469

44704470
ptr= line;
4471-
if (get_next_arg)
4471+
if (mode == GET_NEXT)
44724472
{
44734473
for (; *ptr; ptr++) ;
44744474
if (*(ptr + 1))
@@ -4479,7 +4479,7 @@ char *get_arg(char *line, my_bool get_next_arg)
44794479
/* skip leading white spaces */
44804480
while (my_isspace(charset_info, *ptr))
44814481
ptr++;
4482-
if (*ptr == '\\') // short command was used
4482+
if ((short_cmd= *ptr == '\\')) // short command was used
44834483
ptr+= 2;
44844484
else
44854485
while (*ptr &&!my_isspace(charset_info, *ptr)) // skip command
@@ -4492,24 +4492,28 @@ char *get_arg(char *line, my_bool get_next_arg)
44924492
if (*ptr == '\'' || *ptr == '\"' || *ptr == '`')
44934493
{
44944494
qtype= *ptr;
4495-
quoted= 1;
44964495
ptr++;
44974496
}
44984497
for (start=ptr ; *ptr; ptr++)
44994498
{
4500-
if (*ptr == '\\' && ptr[1]) // escaped character
4499+
if ((*ptr == '\\' && ptr[1]) || // escaped character
4500+
(!short_cmd && qtype && *ptr == qtype && ptr[1] == qtype)) // quote
45014501
{
4502-
// Remove the backslash
4503-
strmov_overlapp(ptr, ptr+1);
4502+
// Remove (or skip) the backslash (or a second quote)
4503+
if (mode != CHECK)
4504+
strmov_overlapp(ptr, ptr+1);
4505+
else
4506+
ptr++;
45044507
}
4505-
else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
4508+
else if (*ptr == (qtype ? qtype : ' '))
45064509
{
4507-
*ptr= 0;
4510+
qtype= 0;
4511+
if (mode != CHECK)
4512+
*ptr= 0;
45084513
break;
45094514
}
45104515
}
4511-
valid_arg= ptr != start;
4512-
return valid_arg ? start : NullS;
4516+
return ptr != start && !qtype ? start : NullS;
45134517
}
45144518

45154519

mysql-test/r/mysql.result

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,14 @@ DROP DATABASE connected_db;
512512
create database `aa``bb````cc`;
513513
DATABASE()
514514
aa`bb``cc
515+
DATABASE()
516+
test
517+
DATABASE()
518+
aa`bb``cc
519+
DATABASE()
520+
test
521+
DATABASE()
522+
aa`bb``cc
515523
drop database `aa``bb````cc`;
516524
a
517525
>>\ndelimiter\n<<

mysql-test/t/mysql.test

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,8 +586,16 @@ DROP DATABASE connected_db;
586586
# USE and names with backticks
587587
#
588588
--write_file $MYSQLTEST_VARDIR/tmp/backticks.sql
589+
\u aa`bb``cc
590+
SELECT DATABASE();
591+
USE test
592+
SELECT DATABASE();
589593
USE aa`bb``cc
590594
SELECT DATABASE();
595+
USE test
596+
SELECT DATABASE();
597+
USE `aa``bb````cc`
598+
SELECT DATABASE();
591599
EOF
592600
create database `aa``bb````cc`;
593601
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/backticks.sql

0 commit comments

Comments
 (0)