Commit b2b69699 authored by Georgi Kodinov's avatar Georgi Kodinov

Bug #59884: setting charset to 2048 crashes

The retrieval of a charset by number was not
doing bounds checking before accessing the internal 
character sets array.
Added checks for valid charset number.
Added asserts for valid charset number to some of 
the internal functions.
Removed one superfluous check for charset_number 0
(since the all_charsets_array[0] is set to 0 anyway) for 
uniformity.
Test suite added.
parent 7d88b552
...@@ -1732,3 +1732,25 @@ set @@session.autocommit=t1_min(), @@session.autocommit=t1_max(), ...@@ -1732,3 +1732,25 @@ set @@session.autocommit=t1_min(), @@session.autocommit=t1_max(),
drop table t1; drop table t1;
drop function t1_min; drop function t1_min;
drop function t1_max; drop function t1_max;
#
# Bug #59884: setting charset to 2048 crashes
#
set session character_set_results = 2048;
ERROR 42000: Unknown character set: '2048'
set session character_set_client=2048;
ERROR 42000: Unknown character set: '2048'
set session character_set_connection=2048;
ERROR 42000: Unknown character set: '2048'
set session character_set_server=2048;
ERROR 42000: Unknown character set: '2048'
set session collation_server=2048;
ERROR HY000: Unknown collation: '2048'
set session character_set_filesystem=2048;
ERROR 42000: Unknown character set: '2048'
set session character_set_database=2048;
ERROR 42000: Unknown character set: '2048'
set session collation_connection=2048;
ERROR HY000: Unknown collation: '2048'
set session collation_database=2048;
ERROR HY000: Unknown collation: '2048'
End of 5.5 tests
...@@ -1476,3 +1476,29 @@ drop function t1_max; ...@@ -1476,3 +1476,29 @@ drop function t1_max;
########################################################################### ###########################################################################
--echo #
--echo # Bug #59884: setting charset to 2048 crashes
--echo #
--error ER_UNKNOWN_CHARACTER_SET
set session character_set_results = 2048;
--error ER_UNKNOWN_CHARACTER_SET
set session character_set_client=2048;
--error ER_UNKNOWN_CHARACTER_SET
set session character_set_connection=2048;
--error ER_UNKNOWN_CHARACTER_SET
set session character_set_server=2048;
--error ER_UNKNOWN_COLLATION
set session collation_server=2048;
--error ER_UNKNOWN_CHARACTER_SET
set session character_set_filesystem=2048;
--error ER_UNKNOWN_CHARACTER_SET
set session character_set_database=2048;
--error ER_UNKNOWN_COLLATION
set session collation_connection=2048;
--error ER_UNKNOWN_COLLATION
set session collation_database=2048;
--echo End of 5.5 tests
...@@ -419,6 +419,7 @@ CHARSET_INFO *default_charset_info = &my_charset_latin1; ...@@ -419,6 +419,7 @@ CHARSET_INFO *default_charset_info = &my_charset_latin1;
void add_compiled_collation(CHARSET_INFO *cs) void add_compiled_collation(CHARSET_INFO *cs)
{ {
DBUG_ASSERT(cs->number < array_elements(all_charsets));
all_charsets[cs->number]= cs; all_charsets[cs->number]= cs;
cs->state|= MY_CS_AVAILABLE; cs->state|= MY_CS_AVAILABLE;
} }
...@@ -529,14 +530,17 @@ uint get_charset_number(const char *charset_name, uint cs_flags) ...@@ -529,14 +530,17 @@ uint get_charset_number(const char *charset_name, uint cs_flags)
const char *get_charset_name(uint charset_number) const char *get_charset_name(uint charset_number)
{ {
CHARSET_INFO *cs;
my_pthread_once(&charsets_initialized, init_available_charsets); my_pthread_once(&charsets_initialized, init_available_charsets);
cs=all_charsets[charset_number]; if (charset_number < array_elements(all_charsets))
if (cs && (cs->number == charset_number) && cs->name ) {
CHARSET_INFO *cs= all_charsets[charset_number];
if (cs && (cs->number == charset_number) && cs->name)
return (char*) cs->name; return (char*) cs->name;
}
return (char*) "?"; /* this mimics find_type() */ return "?"; /* this mimics find_type() */
} }
...@@ -545,6 +549,8 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) ...@@ -545,6 +549,8 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
char buf[FN_REFLEN]; char buf[FN_REFLEN];
CHARSET_INFO *cs; CHARSET_INFO *cs;
DBUG_ASSERT(cs_number < array_elements(all_charsets));
if ((cs= all_charsets[cs_number])) if ((cs= all_charsets[cs_number]))
{ {
if (cs->state & MY_CS_READY) /* if CS is already initialized */ if (cs->state & MY_CS_READY) /* if CS is already initialized */
...@@ -590,7 +596,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags) ...@@ -590,7 +596,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags)
my_pthread_once(&charsets_initialized, init_available_charsets); my_pthread_once(&charsets_initialized, init_available_charsets);
if (!cs_number || cs_number > array_elements(all_charsets)) if (cs_number >= array_elements(all_charsets))
return NULL; return NULL;
cs=get_internal_charset(cs_number, flags); cs=get_internal_charset(cs_number, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment