diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-09-18 09:09:27 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-09-18 09:09:27 +0200 |
commit | a5d7e701196052f4a6605f465953098eba37a7aa (patch) | |
tree | 9c91881a3963fe49277e12167a9e6895f2c368f2 | |
parent | 68df7a0137f15ffe57e4dec0adeeb3989930acf2 (diff) | |
download | mariadb-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.result | 2 | ||||
-rw-r--r-- | mysql-test/std_data/mdev5029.frm | bin | 0 -> 8602 bytes | |||
-rw-r--r-- | mysql-test/t/bad_frm_crash_5029.test | 11 | ||||
-rw-r--r-- | sql/table.cc | 13 |
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 Binary files differnew file mode 100644 index 00000000000..de169a20953 --- /dev/null +++ b/mysql-test/std_data/mdev5029.frm 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) |