Commit 7f9f3139 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-7333 "'show table status like 'table_name'" on tokudb table lead to MariaDB crash

adjust enum values when reading them from frm
parent 2ab49689
call mtr.add_suppression("bad_row_type.frm: invalid value 11 for the field row_format");
select * from bad_row_type;
category_id category_name
show create table bad_row_type;
Table Create Table
bad_row_type CREATE TABLE `bad_row_type` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`category_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
show table status like 'bad_row_type';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
bad_row_type MyISAM 10 Dynamic 0 0 0 281474976710655 1024 0 1 x x NULL utf8_general_ci NULL
drop table bad_row_type;
#
# MDEV-7333 "'show table status like 'table_name'" on tokudb table lead to MariaDB crash
#
let $datadir= `select @@datadir`;
call mtr.add_suppression("bad_row_type.frm: invalid value 11 for the field row_format");
copy_file std_data/bad_row_type.MYD $datadir/test/bad_row_type.MYD;
copy_file std_data/bad_row_type.MYI $datadir/test/bad_row_type.MYI;
copy_file std_data/bad_row_type.frm $datadir/test/bad_row_type.frm;
select * from bad_row_type;
show create table bad_row_type;
replace_column 12 x 13 x;
show table status like 'bad_row_type';
drop table bad_row_type;
...@@ -373,6 +373,9 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ...@@ -373,6 +373,9 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
/** Unused. Reserved for future versions. */ /** Unused. Reserved for future versions. */
ROW_TYPE_PAGE }; ROW_TYPE_PAGE };
/* not part of the enum, so that it shouldn't be in switch(row_type) */
#define ROW_TYPE_MAX ((uint)ROW_TYPE_PAGE + 1)
enum enum_binlog_func { enum enum_binlog_func {
BFN_RESET_LOGS= 1, BFN_RESET_LOGS= 1,
BFN_RESET_SLAVE= 2, BFN_RESET_SLAVE= 2,
...@@ -1248,7 +1251,7 @@ class partition_info; ...@@ -1248,7 +1251,7 @@ class partition_info;
struct st_partition_iter; struct st_partition_iter;
#define NOT_A_PARTITION_ID ((uint32)-1) #define NOT_A_PARTITION_ID ((uint32)-1)
enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES }; enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES, HA_CHOICE_MAX };
typedef struct st_ha_create_information typedef struct st_ha_create_information
{ {
......
...@@ -890,6 +890,23 @@ static bool create_key_infos(uchar *strpos, uint keys, KEY *keyinfo, ...@@ -890,6 +890,23 @@ static bool create_key_infos(uchar *strpos, uint keys, KEY *keyinfo,
return 0; return 0;
} }
/** ensures that the enum value (read from frm) is within limits
if not - issues a warning and resets the value to 0
(that is, 0 is assumed to be a default value)
*/
static uint enum_value_with_check(THD *thd, TABLE_SHARE *share,
const char *name, uint value, uint limit)
{
if (value < limit)
return value;
sql_print_warning("%s.frm: invalid value %d for the field %s",
share->normalized_path.str, value, name);
return 0;
}
/* /*
Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
*/ */
...@@ -983,9 +1000,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ...@@ -983,9 +1000,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (!head[32]) // New frm file in 3.23 if (!head[32]) // New frm file in 3.23
{ {
share->avg_row_length= uint4korr(head+34); share->avg_row_length= uint4korr(head+34);
share->transactional= (ha_choice) (head[39] & 3); share->transactional= (ha_choice)
share->page_checksum= (ha_choice) ((head[39] >> 2) & 3); enum_value_with_check(thd, share, "transactional", (head[39] & 3), HA_CHOICE_MAX);
share->row_type= (row_type) head[40]; share->page_checksum= (ha_choice)
enum_value_with_check(thd, share, "page_checksum", (head[39] >> 2) & 3, HA_CHOICE_MAX);
share->row_type= (row_type)
enum_value_with_check(thd, share, "row_format", head[40], ROW_TYPE_MAX);
share->table_charset= get_charset((((uint) head[41]) << 8) + share->table_charset= get_charset((((uint) head[41]) << 8) +
(uint) head[38],MYF(0)); (uint) head[38],MYF(0));
share->null_field_first= 1; share->null_field_first= 1;
......
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