Commit 941ca92a authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-11369: Perform validation at IMPORT TABLESPACE

btr_cur_instant_root_init(): Check the "infimum" and "supremum"
record strings already here, and not later in btr_cur_instant_root_init().
In this way, we can properly reject files from later versions where
instant ALTER TABLE could support further operations that change the
format of InnoDB clustered indexes.
parent 2badefb0
...@@ -392,24 +392,28 @@ when loading a table definition. ...@@ -392,24 +392,28 @@ when loading a table definition.
@return error code @return error code
@retval DB_SUCCESS if no error occurred @retval DB_SUCCESS if no error occurred
@retval DB_CORRUPTION if any corruption was noticed */ @retval DB_CORRUPTION if any corruption was noticed */
static static dberr_t btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr)
dberr_t
btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr)
{ {
ut_ad(index->is_primary()); ut_ad(index->is_primary());
ut_ad(index->n_core_null_bytes == dict_index_t::NO_CORE_NULL_BYTES); ut_ad(index->n_core_null_bytes == dict_index_t::NO_CORE_NULL_BYTES);
ut_ad(index->table->supports_instant()); ut_ad(index->table->supports_instant());
ut_ad(index->table->is_readable()); ut_ad(index->table->is_readable());
page_t* root = btr_root_get(index, mtr); const fil_space_t* space = index->table->space;
if (!space) {
if (!root || btr_cur_instant_root_init(index, root)) { unreadable:
ib::error() << "Table " << index->table->name ib::error() << "Table " << index->table->name
<< " has an unreadable root page"; << " has an unreadable root page";
index->table->corrupted = true; index->table->corrupted = true;
return DB_CORRUPTION; return DB_CORRUPTION;
} }
page_t* root = btr_root_get(index, mtr);
if (!root || btr_cur_instant_root_init(index, root)) {
goto unreadable;
}
ut_ad(index->n_core_null_bytes != dict_index_t::NO_CORE_NULL_BYTES); ut_ad(index->n_core_null_bytes != dict_index_t::NO_CORE_NULL_BYTES);
if (fil_page_get_type(root) == FIL_PAGE_INDEX) { if (fil_page_get_type(root) == FIL_PAGE_INDEX) {
...@@ -417,17 +421,6 @@ btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr) ...@@ -417,17 +421,6 @@ btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr)
return DB_SUCCESS; return DB_SUCCESS;
} }
/* In a later format, these fields in a FIL_PAGE_TYPE_INSTANT
root page could be repurposed for something else. */
if (memcmp(page_get_infimum_rec(root), "infimum", 8)
|| memcmp(page_get_supremum_rec(root), "supremum", 8)) {
incompatible:
ib::error() << "Table " << index->table->name
<< " contains unrecognizable instant ALTER metadata";
index->table->corrupted = true;
return DB_CORRUPTION;
}
btr_cur_t cur; btr_cur_t cur;
dberr_t err = btr_cur_open_at_index_side(true, index, BTR_SEARCH_LEAF, dberr_t err = btr_cur_open_at_index_side(true, index, BTR_SEARCH_LEAF,
&cur, 0, mtr); &cur, 0, mtr);
...@@ -466,7 +459,11 @@ btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr) ...@@ -466,7 +459,11 @@ btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr)
if (info_bits != REC_INFO_MIN_REC_FLAG if (info_bits != REC_INFO_MIN_REC_FLAG
|| (comp && rec_get_status(rec) != REC_STATUS_COLUMNS_ADDED)) { || (comp && rec_get_status(rec) != REC_STATUS_COLUMNS_ADDED)) {
goto incompatible; incompatible:
ib::error() << "Table " << index->table->name
<< " contains unrecognizable instant ALTER metadata";
index->table->corrupted = true;
return DB_CORRUPTION;
} }
/* Read the metadata. We can get here on server restart /* Read the metadata. We can get here on server restart
...@@ -558,8 +555,7 @@ index root page. ...@@ -558,8 +555,7 @@ index root page.
@param[in] index clustered index that is on its first access @param[in] index clustered index that is on its first access
@param[in] page clustered index root page @param[in] page clustered index root page
@return whether the page is corrupted */ @return whether the page is corrupted */
bool bool btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
{ {
ut_ad(page_is_root(page)); ut_ad(page_is_root(page));
ut_ad(!page_is_comp(page) == !dict_table_is_comp(index->table)); ut_ad(!page_is_comp(page) == !dict_table_is_comp(index->table));
...@@ -590,7 +586,8 @@ btr_cur_instant_root_init(dict_index_t* index, const page_t* page) ...@@ -590,7 +586,8 @@ btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
break; break;
} }
uint16_t n = page_get_instant(page); const uint16_t n = page_get_instant(page);
if (n < index->n_uniq + DATA_ROLL_PTR || n > index->n_fields) { if (n < index->n_uniq + DATA_ROLL_PTR || n > index->n_fields) {
/* The PRIMARY KEY (or hidden DB_ROW_ID) and /* The PRIMARY KEY (or hidden DB_ROW_ID) and
DB_TRX_ID,DB_ROLL_PTR columns must always be present DB_TRX_ID,DB_ROLL_PTR columns must always be present
...@@ -599,6 +596,14 @@ btr_cur_instant_root_init(dict_index_t* index, const page_t* page) ...@@ -599,6 +596,14 @@ btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
dictionary. */ dictionary. */
return true; return true;
} }
if (memcmp(page_get_infimum_rec(page), "infimum", 8)
|| memcmp(page_get_supremum_rec(page), "supremum", 8)) {
/* In a later format, these fields in a FIL_PAGE_TYPE_INSTANT
root page could be repurposed for something else. */
return true;
}
index->n_core_fields = n; index->n_core_fields = n;
ut_ad(!index->is_dummy); ut_ad(!index->is_dummy);
ut_d(index->is_dummy = true); ut_d(index->is_dummy = true);
......
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