diff options
author | Sergei Golubchik <sergii@pisem.net> | 2015-01-13 19:27:28 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2015-01-13 19:27:28 +0100 |
commit | 7f9f3139d79d2b5e0a1c1eb47b02a5976d572670 (patch) | |
tree | e354cf1f820aa0183db063fff75adc1cc27484f8 /sql | |
parent | 2ab49689c689b1c1daeb080ea568c268c5256952 (diff) | |
download | mariadb-git-7f9f3139d79d2b5e0a1c1eb47b02a5976d572670.tar.gz |
MDEV-7333 "'show table status like 'table_name'" on tokudb table lead to MariaDB crash
adjust enum values when reading them from frm
Diffstat (limited to 'sql')
-rw-r--r-- | sql/handler.h | 5 | ||||
-rw-r--r-- | sql/table.cc | 26 |
2 files changed, 27 insertions, 4 deletions
diff --git a/sql/handler.h b/sql/handler.h index 5c902e604e9..8f8b4fd93af 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -373,6 +373,9 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, /** Unused. Reserved for future versions. */ 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 { BFN_RESET_LOGS= 1, BFN_RESET_SLAVE= 2, @@ -1248,7 +1251,7 @@ class partition_info; struct st_partition_iter; #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 { diff --git a/sql/table.cc b/sql/table.cc index 4ce70987334..a4cf9939845 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -890,6 +890,23 @@ static bool create_key_infos(uchar *strpos, uint keys, KEY *keyinfo, 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 */ @@ -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 { share->avg_row_length= uint4korr(head+34); - share->transactional= (ha_choice) (head[39] & 3); - share->page_checksum= (ha_choice) ((head[39] >> 2) & 3); - share->row_type= (row_type) head[40]; + share->transactional= (ha_choice) + enum_value_with_check(thd, share, "transactional", (head[39] & 3), HA_CHOICE_MAX); + 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) + (uint) head[38],MYF(0)); share->null_field_first= 1; |