Skip to content

Commit 7d8028a

Browse files
committed
Bug #19953349: MYSQL_CONFIG_EDITOR DOES NOT ESCAPE STRINGS
RB#25710 mysql_config_editor was not surrounding the values it was putting into the special login file with double quotes. This means any spaces or special symbols will break the value and will not be sent down to the mysql command line tool when the login path is used. Fixed by making sure mysql_config_editor puts these values into double quotes and also that the double quote symbols are escaped. Test case added.
1 parent 97ef39e commit 7d8028a

File tree

6 files changed

+109
-58
lines changed

6 files changed

+109
-58
lines changed

client/mysql_config_editor.cc

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2012, 2020, Oracle and/or its affiliates.
2+
Copyright (c) 2012, 2021, Oracle and/or its affiliates.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License, version 2.0,
@@ -515,24 +515,24 @@ static int set_command(void) {
515515
if (opt_user) /* --user */
516516
{
517517
dynstr_append(&path_buf, "\nuser = ");
518-
dynstr_append(&path_buf, opt_user);
518+
dynstr_append_quoted(&path_buf, "\"", 1, opt_user, NullS);
519519
}
520520

521521
if (opt_password) /* --password */
522522
{
523523
dynstr_append(&path_buf, "\npassword = ");
524-
dynstr_append(&path_buf, opt_password);
524+
dynstr_append_quoted(&path_buf, "\"", 1, opt_password, NullS);
525525
}
526526

527527
if (opt_host) /* --host */
528528
{
529529
dynstr_append(&path_buf, "\nhost = ");
530-
dynstr_append(&path_buf, opt_host);
530+
dynstr_append_quoted(&path_buf, "\"", 1, opt_host, NullS);
531531
}
532532

533533
if (opt_socket) {
534534
dynstr_append(&path_buf, "\nsocket = ");
535-
dynstr_append(&path_buf, opt_socket);
535+
dynstr_append_quoted(&path_buf, "\"", 1, opt_socket, NullS);
536536
}
537537

538538
if (opt_port) {

include/my_sys.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
1+
/* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License, version 2.0,
@@ -801,6 +801,8 @@ extern bool dynstr_append(DYNAMIC_STRING *str, const char *append);
801801
bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, size_t length);
802802
extern bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append,
803803
...);
804+
extern bool dynstr_append_quoted(DYNAMIC_STRING *str, const char *quote_str,
805+
const uint quote_len, const char *append, ...);
804806
extern bool dynstr_set(DYNAMIC_STRING *str, const char *init_str);
805807
extern bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size);
806808
extern bool dynstr_trunc(DYNAMIC_STRING *str, size_t n);

mysql-test/r/mysql_config_editor.result

+46-33
Original file line numberDiff line numberDiff line change
@@ -20,54 +20,54 @@
2020
#
2121
# Default path
2222
[client]
23-
user = test_user1
24-
host = localhost
23+
user = "test_user1"
24+
host = "localhost"
2525

2626
#
2727
# test-login-path1
2828
[test-login-path1]
29-
user = test_user2
30-
host = 127.0.0.1
29+
user = "test_user2"
30+
host = "127.0.0.1"
3131

3232
#
3333
# test-login-path2
3434
[test-login-path2]
35-
user = test_user3
36-
host = www.mysql.com
35+
user = "test_user3"
36+
host = "www.mysql.com"
3737

3838
#
3939
# all the paths
4040
[client]
41-
user = test_user1
42-
host = localhost
41+
user = "test_user1"
42+
host = "localhost"
4343
[test-login-path1]
44-
user = test_user2
45-
host = 127.0.0.1
44+
user = "test_user2"
45+
host = "127.0.0.1"
4646
[test-login-path2]
47-
user = test_user3
48-
host = www.mysql.com
47+
user = "test_user3"
48+
host = "www.mysql.com"
4949
[test-login-path3]
50-
user = test_user4
51-
host = 127.0.0.1
52-
socket = /tmp/configtest.sock
50+
user = "test_user4"
51+
host = "127.0.0.1"
52+
socket = "/tmp/configtest.sock"
5353
port = 15000
5454

5555
#
5656
# Overwrite existing paths, test-login-path2 & default
5757
#
5858
# all the paths again
5959
[test-login-path1]
60-
user = test_user2
61-
host = 127.0.0.1
60+
user = "test_user2"
61+
host = "127.0.0.1"
6262
[test-login-path3]
63-
user = test_user4
64-
host = 127.0.0.1
65-
socket = /tmp/configtest.sock
63+
user = "test_user4"
64+
host = "127.0.0.1"
65+
socket = "/tmp/configtest.sock"
6666
port = 15000
6767
[test-login-path2]
68-
user = test_user4
68+
user = "test_user4"
6969
[client]
70-
user = test_user5
70+
user = "test_user5"
7171

7272
################################################
7373
# Tests for mysql_config_editor's remove command
@@ -86,10 +86,10 @@ user = test_user5
8686
#
8787
# using all
8888
[test-login-path3]
89-
user = test_user4
90-
host = 127.0.0.1
89+
user = "test_user4"
90+
host = "127.0.0.1"
9191
[test-login-path2]
92-
user = test_user4
92+
user = "test_user4"
9393

9494
###############################################
9595
# Tests for mysql_config_editor's reset command
@@ -189,18 +189,18 @@ mysqld is alive
189189

190190
# Printing all the paths..
191191
[client]
192-
user = test_user1
193-
host = localhost
192+
user = "test_user1"
193+
host = "localhost"
194194
[test-login-path1]
195-
user = test_user2
196-
host = 127.0.0.1
195+
user = "test_user2"
196+
host = "127.0.0.1"
197197
[test-login-path2]
198-
user = test_user3
199-
host = 127.0.0.1
200-
socket = /tmp/configtest.sock
198+
user = "test_user3"
199+
host = "127.0.0.1"
200+
socket = "/tmp/configtest.sock"
201201
port = 15000
202202
[client_suffix1]
203-
user = test_user3
203+
user = "test_user3"
204204

205205
# Now trying to connect using 'test_user3'
206206
# Note : In this case options from login
@@ -327,3 +327,16 @@ mysqld is alive
327327
# Cleanup
328328
DROP USER 'test#user1'@'localhost';
329329
# End of 5.6 tests
330+
#
331+
# Bug #19953349: MYSQL_CONFIG_EDITOR DOES NOT ESCAPE STRINGS
332+
#
333+
CREATE USER 'test1 test1'@'localhost';
334+
test: must contain space
335+
[test11]
336+
user = "test1 test1"
337+
host = "127.0.0.1"
338+
# test: must not fail with a space in the name
339+
mysqld is alive
340+
# cleanup
341+
DROP USER 'test1 test1'@'localhost';
342+
# End of 8.0 tests

mysql-test/suite/interactive_utilities/r/mysql_config_editor.result

+6-6
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,17 @@ user_2@localhost user_2@localhost
8888
# .mylogin.cnf file before cleanup #
8989
############################################
9090
[login_path_1]
91-
user = user_1
91+
user = "user_1"
9292
password = *****
93-
host = localhost
93+
host = "localhost"
9494
[login_path_3]
95-
user = user_3
95+
user = "user_3"
9696
password = *****
97-
host = localhost
97+
host = "localhost"
9898
[login_path_2]
99-
user = user_2
99+
user = "user_2"
100100
password = *****
101-
host = localhost
101+
host = "localhost"
102102

103103
#################################################
104104
# empty .mylogin.cnf file after cleanup #

mysql-test/t/mysql_config_editor.test

+19
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,22 @@ DROP USER 'test#user1'@'localhost';
268268
--remove_file $MYSQL_TEST_LOGIN_FILE
269269

270270
--echo # End of 5.6 tests
271+
272+
--echo #
273+
--echo # Bug #19953349: MYSQL_CONFIG_EDITOR DOES NOT ESCAPE STRINGS
274+
--echo #
275+
276+
CREATE USER 'test1 test1'@'localhost';
277+
278+
--exec $MYSQL_CONFIG_EDITOR set --login-path=test11 --user="test1 test1" --host=127.0.0.1 2>&1
279+
--echo test: must contain space
280+
--exec $MYSQL_CONFIG_EDITOR print --login-path=test11
281+
282+
--echo # test: must not fail with a space in the name
283+
--exec $MYSQLADMIN --no-defaults --login-path=test11 --port=$MASTER_MYPORT ping 2>&1
284+
285+
--echo # cleanup
286+
DROP USER 'test1 test1'@'localhost';
287+
--remove_file $MYSQL_TEST_LOGIN_FILE
288+
289+
--echo # End of 8.0 tests

mysys/my_string.cc

+30-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
1+
/* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License, version 2.0,
@@ -118,7 +118,7 @@ bool dynstr_trunc(DYNAMIC_STRING *str, size_t n) {
118118
}
119119

120120
/*
121-
Concatenates any number of strings, escapes any OS quote in the result then
121+
Concatenates any number of strings, escapes any quote in the result then
122122
surround the whole affair in another set of quotes which is finally appended
123123
to specified DYNAMIC_STRING. This function is especially useful when
124124
building strings to be executed with the system() function.
@@ -133,19 +133,12 @@ bool dynstr_trunc(DYNAMIC_STRING *str, size_t n) {
133133
@return True = Success.
134134
*/
135135

136-
bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) {
137-
#ifdef _WIN32
138-
const char *quote_str = "\"";
139-
const uint quote_len = 1;
140-
#else
141-
const char *quote_str = "\'";
142-
const uint quote_len = 1;
143-
#endif /* _WIN32 */
136+
static bool dynstr_append_quoted_inner(DYNAMIC_STRING *str,
137+
const char *quote_str,
138+
const uint quote_len, const char *append,
139+
va_list dirty_text) {
144140
bool ret = true;
145-
va_list dirty_text;
146-
147141
ret &= dynstr_append_mem(str, quote_str, quote_len); /* Leading quote */
148-
va_start(dirty_text, append);
149142
while (append != NullS) {
150143
const char *cur_pos = append;
151144
const char *next_pos = cur_pos;
@@ -166,6 +159,30 @@ bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) {
166159
return ret;
167160
}
168161

162+
bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) {
163+
#ifdef _WIN32
164+
const char *quote_str = "\"";
165+
const uint quote_len = 1;
166+
#else
167+
const char *quote_str = "\'";
168+
const uint quote_len = 1;
169+
#endif /* _WIN32 */
170+
va_list dirty_text;
171+
172+
va_start(dirty_text, append);
173+
return dynstr_append_quoted_inner(str, quote_str, quote_len, append,
174+
dirty_text);
175+
}
176+
177+
bool dynstr_append_quoted(DYNAMIC_STRING *str, const char *quote_str,
178+
const uint quote_len, const char *append, ...) {
179+
va_list dirty_text;
180+
181+
va_start(dirty_text, append);
182+
return dynstr_append_quoted_inner(str, quote_str, quote_len, append,
183+
dirty_text);
184+
}
185+
169186
void dynstr_free(DYNAMIC_STRING *str) {
170187
my_free(str->str);
171188
str->str = nullptr;

0 commit comments

Comments
 (0)