Skip to content

Commit 941ca92

Browse files
committed
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.
1 parent 2badefb commit 941ca92

File tree

1 file changed

+26
-21
lines changed

1 file changed

+26
-21
lines changed

storage/innobase/btr/btr0cur.cc

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -392,42 +392,35 @@ when loading a table definition.
392392
@return error code
393393
@retval DB_SUCCESS if no error occurred
394394
@retval DB_CORRUPTION if any corruption was noticed */
395-
static
396-
dberr_t
397-
btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr)
395+
static dberr_t btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr)
398396
{
399397
ut_ad(index->is_primary());
400398
ut_ad(index->n_core_null_bytes == dict_index_t::NO_CORE_NULL_BYTES);
401399
ut_ad(index->table->supports_instant());
402400
ut_ad(index->table->is_readable());
403401

404-
page_t* root = btr_root_get(index, mtr);
405-
406-
if (!root || btr_cur_instant_root_init(index, root)) {
402+
const fil_space_t* space = index->table->space;
403+
if (!space) {
404+
unreadable:
407405
ib::error() << "Table " << index->table->name
408406
<< " has an unreadable root page";
409407
index->table->corrupted = true;
410408
return DB_CORRUPTION;
411409
}
412410

411+
page_t* root = btr_root_get(index, mtr);
412+
413+
if (!root || btr_cur_instant_root_init(index, root)) {
414+
goto unreadable;
415+
}
416+
413417
ut_ad(index->n_core_null_bytes != dict_index_t::NO_CORE_NULL_BYTES);
414418

415419
if (fil_page_get_type(root) == FIL_PAGE_INDEX) {
416420
ut_ad(!index->is_instant());
417421
return DB_SUCCESS;
418422
}
419423

420-
/* In a later format, these fields in a FIL_PAGE_TYPE_INSTANT
421-
root page could be repurposed for something else. */
422-
if (memcmp(page_get_infimum_rec(root), "infimum", 8)
423-
|| memcmp(page_get_supremum_rec(root), "supremum", 8)) {
424-
incompatible:
425-
ib::error() << "Table " << index->table->name
426-
<< " contains unrecognizable instant ALTER metadata";
427-
index->table->corrupted = true;
428-
return DB_CORRUPTION;
429-
}
430-
431424
btr_cur_t cur;
432425
dberr_t err = btr_cur_open_at_index_side(true, index, BTR_SEARCH_LEAF,
433426
&cur, 0, mtr);
@@ -466,7 +459,11 @@ btr_cur_instant_init_low(dict_index_t* index, mtr_t* mtr)
466459

467460
if (info_bits != REC_INFO_MIN_REC_FLAG
468461
|| (comp && rec_get_status(rec) != REC_STATUS_COLUMNS_ADDED)) {
469-
goto incompatible;
462+
incompatible:
463+
ib::error() << "Table " << index->table->name
464+
<< " contains unrecognizable instant ALTER metadata";
465+
index->table->corrupted = true;
466+
return DB_CORRUPTION;
470467
}
471468

472469
/* Read the metadata. We can get here on server restart
@@ -558,8 +555,7 @@ index root page.
558555
@param[in] index clustered index that is on its first access
559556
@param[in] page clustered index root page
560557
@return whether the page is corrupted */
561-
bool
562-
btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
558+
bool btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
563559
{
564560
ut_ad(page_is_root(page));
565561
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)
590586
break;
591587
}
592588

593-
uint16_t n = page_get_instant(page);
589+
const uint16_t n = page_get_instant(page);
590+
594591
if (n < index->n_uniq + DATA_ROLL_PTR || n > index->n_fields) {
595592
/* The PRIMARY KEY (or hidden DB_ROW_ID) and
596593
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)
599596
dictionary. */
600597
return true;
601598
}
599+
600+
if (memcmp(page_get_infimum_rec(page), "infimum", 8)
601+
|| memcmp(page_get_supremum_rec(page), "supremum", 8)) {
602+
/* In a later format, these fields in a FIL_PAGE_TYPE_INSTANT
603+
root page could be repurposed for something else. */
604+
return true;
605+
}
606+
602607
index->n_core_fields = n;
603608
ut_ad(!index->is_dummy);
604609
ut_d(index->is_dummy = true);

0 commit comments

Comments
 (0)