Skip to content

Commit 76e0dc1

Browse files
committed
MDEV-34288 SET NAMES DEFAULT crashes mariadbd --collation-server=utf8mb4_unicode_ci
The @@global.character_set_client variable could erroneously be set to a non-default collation of its character set, which further made the `SET NAMES DEFAULT` statement crash the server. Fixing the code to make sure that the global value these variables: @@character_set_client @@character_set_connection @@character_set_server @@character_set_database @@character_set_connection point to the default compiled collations of the character set.
1 parent d619475 commit 76e0dc1

File tree

9 files changed

+156
-16
lines changed

9 files changed

+156
-16
lines changed

mysql-test/main/ctype_utf8mb4_unicode_ci_def.result

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,48 @@ DROP TABLE t1;
99
#
1010
# End of 10.3 tests
1111
#
12+
#
13+
# Start of 10.11 tests
14+
#
15+
#
16+
# MDEV-34288 SET NAMES DEFAULT crashes `mariadbd --collation-server=utf8mb4_unicode_ci`
17+
#
18+
SET NAMES DEFAULT COLLATE latin1_bin;
19+
ERROR 42000: COLLATION 'latin1_bin' is not valid for CHARACTER SET 'utf8mb4'
20+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
21+
@@character_set_connection @@collation_connection @@character_set_results
22+
latin1 latin1_swedish_ci latin1
23+
SET NAMES DEFAULT COLLATE utf8mb4_bin;
24+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
25+
@@character_set_connection @@collation_connection @@character_set_results
26+
utf8mb4 utf8mb4_bin utf8mb4
27+
SET NAMES DEFAULT COLLATE uca1400_ai_ci;
28+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
29+
@@character_set_connection @@collation_connection @@character_set_results
30+
utf8mb4 utf8mb4_uca1400_ai_ci utf8mb4
31+
SET @@global.character_set_client=latin1;
32+
SET NAMES DEFAULT;
33+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
34+
@@character_set_connection @@collation_connection @@character_set_results
35+
latin1 latin1_swedish_ci latin1
36+
SET @@global.character_set_client=utf8mb3;
37+
SET NAMES DEFAULT;
38+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
39+
@@character_set_connection @@collation_connection @@character_set_results
40+
utf8mb3 utf8mb3_general_ci utf8mb3
41+
SET @@global.character_set_client=DEFAULT;
42+
SET NAMES DEFAULT;
43+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
44+
@@character_set_connection @@collation_connection @@character_set_results
45+
utf8mb4 utf8mb4_general_ci utf8mb4
46+
SET NAMES DEFAULT;
47+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
48+
@@character_set_connection @@collation_connection @@character_set_results
49+
utf8mb4 utf8mb4_general_ci utf8mb4
50+
SET NAMES DEFAULT COLLATE DEFAULT;
51+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
52+
@@character_set_connection @@collation_connection @@character_set_results
53+
utf8mb4 utf8mb4_general_ci utf8mb4
54+
#
55+
# End of 10.11 tests
56+
#

mysql-test/main/ctype_utf8mb4_unicode_ci_def.test

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,45 @@ DROP TABLE t1;
1313
--echo #
1414
--echo # End of 10.3 tests
1515
--echo #
16+
17+
18+
--echo #
19+
--echo # Start of 10.11 tests
20+
--echo #
21+
22+
--echo #
23+
--echo # MDEV-34288 SET NAMES DEFAULT crashes `mariadbd --collation-server=utf8mb4_unicode_ci`
24+
--echo #
25+
26+
--error ER_COLLATION_CHARSET_MISMATCH
27+
SET NAMES DEFAULT COLLATE latin1_bin;
28+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
29+
30+
SET NAMES DEFAULT COLLATE utf8mb4_bin;
31+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
32+
33+
SET NAMES DEFAULT COLLATE uca1400_ai_ci;
34+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
35+
36+
SET @@global.character_set_client=latin1;
37+
SET NAMES DEFAULT;
38+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
39+
40+
SET @@global.character_set_client=utf8mb3;
41+
SET NAMES DEFAULT;
42+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
43+
44+
SET @@global.character_set_client=DEFAULT;
45+
SET NAMES DEFAULT;
46+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
47+
48+
SET NAMES DEFAULT;
49+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
50+
51+
SET NAMES DEFAULT COLLATE DEFAULT;
52+
SELECT @@character_set_connection, @@collation_connection, @@character_set_results;
53+
54+
55+
--echo #
56+
--echo # End of 10.11 tests
57+
--echo #

sql/lex_charset.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,12 @@ class Lex_extended_collation_st
288288
DBUG_ASSERT(0);
289289
return m_ci->coll_name;
290290
}
291+
static Lex_extended_collation_st collate_default()
292+
{
293+
Lex_extended_collation_st res;
294+
res.set_collate_default();
295+
return res;
296+
}
291297
void set_collate_default()
292298
{
293299
m_ci= &my_collation_contextually_typed_default;

sql/mysqld.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4329,8 +4329,10 @@ static int init_common_variables()
43294329
if (is_supported_parser_charset(default_charset_info))
43304330
{
43314331
global_system_variables.collation_connection= default_charset_info;
4332-
global_system_variables.character_set_results= default_charset_info;
4333-
global_system_variables.character_set_client= default_charset_info;
4332+
global_system_variables.character_set_results=
4333+
global_system_variables.character_set_client=
4334+
Lex_exact_charset_opt_extended_collate(default_charset_info, true).
4335+
find_default_collation();
43344336
}
43354337
else
43364338
{

sql/sql_lex.cc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12131,10 +12131,31 @@ bool LEX::sp_create_set_password_instr(THD *thd,
1213112131
}
1213212132

1213312133

12134+
/*
12135+
Handle the SET NAMES statement variants, e.g.:
12136+
SET NAMES DEFAULT;
12137+
SET NAMES DEFAULT COLLATE DEFAULT;
12138+
SET NAMES DEFAULT COLLATE latin1_bin;
12139+
SET NAMES latin1;
12140+
SET NAMES latin1 COLLATE DEFAULT;
12141+
SET NAMES latin1 COLLATE latin1_bin;
12142+
SET NAMES utf8mb4 COLLATE uca1400_ai_ci;
12143+
12144+
@param pos - The position of the keyword `NAMES` inside the query
12145+
@param cs - The character set part, or nullptr if DEFAULT
12146+
@param cl - The collation (explicit or contextually typed)
12147+
@param no_lookahead - The tokinizer lookahead state
12148+
*/
1213412149
bool LEX::set_names(const char *pos,
12135-
const Lex_exact_charset_opt_extended_collate &cscl,
12150+
CHARSET_INFO *cs,
12151+
const Lex_extended_collation_st &cl,
1213612152
bool no_lookahead)
1213712153
{
12154+
CHARSET_INFO *def= global_system_variables.character_set_client;
12155+
Lex_exact_charset_opt_extended_collate cscl(cs ? cs : def, true);
12156+
if (cscl.merge_collation_override(cl))
12157+
return true;
12158+
1213812159
if (sp_create_assignment_lex(thd, pos))
1213912160
return true;
1214012161
CHARSET_INFO *ci= cscl.collation().charset_info();

sql/sql_lex.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3873,7 +3873,8 @@ struct LEX: public Query_tables_list
38733873
int case_stmt_action_then();
38743874
bool setup_select_in_parentheses();
38753875
bool set_names(const char *pos,
3876-
const Lex_exact_charset_opt_extended_collate &cs,
3876+
CHARSET_INFO *cs,
3877+
const Lex_extended_collation_st &coll,
38773878
bool no_lookahead);
38783879
bool set_trigger_new_row(const LEX_CSTRING *name, Item *val);
38793880
bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,

sql/sql_yacc.yy

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16671,18 +16671,15 @@ option_value_no_option_type:
1667116671
}
1667216672
| NAMES_SYM charset_name_or_default
1667316673
{
16674-
CHARSET_INFO *def= global_system_variables.character_set_client;
16675-
Lex_exact_charset_opt_extended_collate tmp($2 ? $2 : def, false);
16676-
if (Lex->set_names($1.pos(), tmp, yychar == YYEMPTY))
16674+
if (Lex->set_names($1.pos(), $2,
16675+
Lex_extended_collation_st::collate_default(),
16676+
yychar == YYEMPTY))
1667716677
MYSQL_YYABORT;
1667816678
}
1667916679
| NAMES_SYM charset_name_or_default
1668016680
COLLATE_SYM collation_name_or_default
1668116681
{
16682-
CHARSET_INFO *def= global_system_variables.character_set_client;
16683-
Lex_exact_charset_opt_extended_collate tmp($2 ? $2 : def, false);
16684-
if (tmp.merge_collation($4) ||
16685-
Lex->set_names($1.pos(), tmp, yychar == YYEMPTY))
16682+
if (Lex->set_names($1.pos(), $2, $4, yychar == YYEMPTY))
1668616683
MYSQL_YYABORT;
1668716684
}
1668816685
| DEFAULT ROLE_SYM grant_role

sql/sys_vars.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ static Sys_var_struct Sys_character_set_system(
824824
READ_ONLY GLOBAL_VAR(system_charset_info), NO_CMD_LINE,
825825
offsetof(CHARSET_INFO, cs_name.str), DEFAULT(0));
826826

827-
static Sys_var_struct Sys_character_set_server(
827+
static Sys_var_charset Sys_character_set_server(
828828
"character_set_server", "The default character set",
829829
SESSION_VAR(collation_server), NO_CMD_LINE,
830830
offsetof(CHARSET_INFO, cs_name.str), DEFAULT(&default_charset_info),
@@ -838,7 +838,7 @@ static bool check_charset_db(sys_var *self, THD *thd, set_var *var)
838838
var->save_result.ptr= thd->db_charset;
839839
return false;
840840
}
841-
static Sys_var_struct Sys_character_set_database(
841+
static Sys_var_charset Sys_character_set_database(
842842
"character_set_database",
843843
"The character set used by the default database",
844844
SESSION_VAR(collation_database), NO_CMD_LINE,
@@ -862,7 +862,8 @@ static bool fix_thd_charset(sys_var *self, THD *thd, enum_var_type type)
862862
thd->update_charset();
863863
return false;
864864
}
865-
static Sys_var_struct Sys_character_set_client(
865+
866+
static Sys_var_charset Sys_character_set_client(
866867
"character_set_client", "The character set for statements "
867868
"that arrive from the client",
868869
NO_SET_STMT SESSION_VAR(character_set_client), NO_CMD_LINE,
@@ -872,7 +873,7 @@ static Sys_var_struct Sys_character_set_client(
872873
// for check changing
873874
export sys_var *Sys_character_set_client_ptr= &Sys_character_set_client;
874875

875-
static Sys_var_struct Sys_character_set_connection(
876+
static Sys_var_charset Sys_character_set_connection(
876877
"character_set_connection", "The character set used for "
877878
"literals that do not have a character set introducer and for "
878879
"number-to-string conversion",
@@ -883,7 +884,7 @@ static Sys_var_struct Sys_character_set_connection(
883884
// for check changing
884885
export sys_var *Sys_character_set_connection_ptr= &Sys_character_set_connection;
885886

886-
static Sys_var_struct Sys_character_set_results(
887+
static Sys_var_charset Sys_character_set_results(
887888
"character_set_results", "The character set used for returning "
888889
"query results to the client",
889890
SESSION_VAR(character_set_results), NO_CMD_LINE,

sql/sys_vars.inl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,31 @@ public:
21662166
{ return valptr(thd, *(uchar**)option.def_value); }
21672167
};
21682168

2169+
2170+
/**
2171+
The class to store character sets.
2172+
*/
2173+
class Sys_var_charset: public Sys_var_struct
2174+
{
2175+
public:
2176+
using Sys_var_struct::Sys_var_struct;
2177+
void global_save_default(THD *thd, set_var *var)
2178+
{
2179+
/*
2180+
The default value can point to an arbitrary collation,
2181+
e.g. default_charset_info.
2182+
Let's convert it to the compiled default collation.
2183+
This makes the code easier in various places such as SET NAMES.
2184+
*/
2185+
void **default_value= reinterpret_cast<void**>(option.def_value);
2186+
var->save_result.ptr=
2187+
Lex_exact_charset_opt_extended_collate((CHARSET_INFO *) *default_value,
2188+
true).
2189+
find_default_collation();
2190+
}
2191+
};
2192+
2193+
21692194
/**
21702195
The class for variables that store time zones
21712196

0 commit comments

Comments
 (0)