summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2015-01-13 19:27:28 +0100
committerSergei Golubchik <sergii@pisem.net>2015-01-13 19:27:28 +0100
commit7f9f3139d79d2b5e0a1c1eb47b02a5976d572670 (patch)
treee354cf1f820aa0183db063fff75adc1cc27484f8 /sql
parent2ab49689c689b1c1daeb080ea568c268c5256952 (diff)
downloadmariadb-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.h5
-rw-r--r--sql/table.cc26
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;