summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-09-18 09:09:27 +0200
committerSergei Golubchik <sergii@pisem.net>2013-09-18 09:09:27 +0200
commita5d7e701196052f4a6605f465953098eba37a7aa (patch)
tree9c91881a3963fe49277e12167a9e6895f2c368f2
parent68df7a0137f15ffe57e4dec0adeeb3989930acf2 (diff)
downloadmariadb-git-a5d7e701196052f4a6605f465953098eba37a7aa.tar.gz
MDEV-5029 Crash in MariaDB 5.5.33 with .frm from older MariaDB release
don't set TABLE_SHARE::keys before TABLE_SHARE::key_info is set, otherwise an error might leave only the first property set and it will confuse TABLE_SHARE::destroy()
-rw-r--r--mysql-test/r/bad_frm_crash_5029.result2
-rw-r--r--mysql-test/std_data/mdev5029.frmbin0 -> 8602 bytes
-rw-r--r--mysql-test/t/bad_frm_crash_5029.test11
-rw-r--r--sql/table.cc13
4 files changed, 21 insertions, 5 deletions
diff --git a/mysql-test/r/bad_frm_crash_5029.result b/mysql-test/r/bad_frm_crash_5029.result
new file mode 100644
index 00000000000..7a829c8f6ba
--- /dev/null
+++ b/mysql-test/r/bad_frm_crash_5029.result
@@ -0,0 +1,2 @@
+show create table t1;
+ERROR 42000: Unknown storage engine 'InnoDB'
diff --git a/mysql-test/std_data/mdev5029.frm b/mysql-test/std_data/mdev5029.frm
new file mode 100644
index 00000000000..de169a20953
--- /dev/null
+++ b/mysql-test/std_data/mdev5029.frm
Binary files differ
diff --git a/mysql-test/t/bad_frm_crash_5029.test b/mysql-test/t/bad_frm_crash_5029.test
new file mode 100644
index 00000000000..b15c37fbc6d
--- /dev/null
+++ b/mysql-test/t/bad_frm_crash_5029.test
@@ -0,0 +1,11 @@
+#
+# MDEV-5029 Crash in MariaDB 5.5.33 with .frm from older MariaDB release
+#
+# a.k.a. fail to open an frm with indexes:
+
+let $datadir=`select @@datadir`;
+copy_file std_data/mdev5029.frm $datadir/test/t1.frm;
+--error ER_UNKNOWN_STORAGE_ENGINE
+show create table t1;
+remove_file $datadir/test/t1.frm;
+
diff --git a/sql/table.cc b/sql/table.cc
index 43cbfb7ca56..9e71680652a 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -890,6 +890,9 @@ static bool create_key_infos(uchar *strpos, uint keys, KEY *keyinfo, uint new_fr
DBUG_ASSERT(test(keyinfo->flags & HA_USES_COMMENT) ==
(keyinfo->comment.length > 0));
}
+
+ share->keys= keys; // do it *after* all key_info's are initialized
+
return 0;
}
@@ -1020,12 +1023,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
goto err; /* purecov: inspected */
if (disk_buff[0] & 0x80)
{
- share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
+ keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
share->key_parts= key_parts= uint2korr(disk_buff+2);
}
else
{
- share->keys= keys= disk_buff[0];
+ keys= disk_buff[0];
share->key_parts= key_parts= disk_buff[1];
}
share->keys_for_keyread.init(0);
@@ -1283,7 +1286,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
share->comment.length);
}
- DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length, vcol_screen_length));
+ DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, keys,n_length,int_length, com_length, vcol_screen_length));
if (!(field_ptr = (Field **)
@@ -1671,7 +1674,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
}
}
- for (uint key=0 ; key < share->keys ; key++,keyinfo++)
+ for (uint key=0 ; key < keys ; key++,keyinfo++)
{
uint usable_parts= 0;
keyinfo->name=(char*) share->keynames.type_names[key];
@@ -1945,7 +1948,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
{
reg_field= *share->found_next_number_field;
if ((int) (share->next_number_index= (uint)
- find_ref_key(share->key_info, share->keys,
+ find_ref_key(share->key_info, keys,
share->default_values, reg_field,
&share->next_number_key_offset,
&share->next_number_keypart)) < 0)