@ -265,6 +265,87 @@ xb_fil_cur_open(
return ( XB_FIL_CUR_SUCCESS ) ;
}
static bool page_is_corrupted ( byte * page , ulint page_no , xb_fil_cur_t * cursor , fil_space_t * space )
{
byte tmp_frame [ UNIV_PAGE_SIZE_MAX ] ;
byte tmp_page [ UNIV_PAGE_SIZE_MAX ] ;
ulint page_type = mach_read_from_2 ( page + FIL_PAGE_TYPE ) ;
/* We ignore the doublewrite buffer pages.*/
if ( cursor - > space_id = = TRX_SYS_SPACE
& & page_no > = FSP_EXTENT_SIZE
& & page_no < FSP_EXTENT_SIZE * 3 ) {
return false ;
}
/* Validate page number. */
if ( mach_read_from_4 ( page + FIL_PAGE_OFFSET ) ! = page_no
& & space - > id ! = TRX_SYS_SPACE ) {
/* On pages that are not all zero, the
page number must match .
There may be a mismatch on tablespace ID ,
because files may be renamed during backup .
We disable the page number check
on the system tablespace , because it may consist
of multiple files , and here we count the pages
from the start of each file . )
The first 38 and last 8 bytes are never encrypted . */
const ulint * p = reinterpret_cast < ulint * > ( page ) ;
const ulint * const end = reinterpret_cast < ulint * > (
page + cursor - > page_size ) ;
do {
if ( * p + + ) {
return true ;
}
} while ( p ! = end ) ;
/* Whole zero page is valid. */
return false ;
}
/* Validate encrypted pages. */
if ( mach_read_from_4 ( page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION ) & &
( space - > crypt_data & & space - > crypt_data - > type ! = CRYPT_SCHEME_UNENCRYPTED ) ) {
if ( ! fil_space_verify_crypt_checksum ( page , cursor - > zip_size ) )
return true ;
/* Compressed encrypted need to be unencryped and uncompressed for verification. */
if ( page_type ! = FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED & & ! opt_extended_validation )
return false ;
memcpy ( tmp_page , page , cursor - > page_size ) ;
bool decrypted = false ;
if ( ! fil_space_decrypt ( space , tmp_frame , tmp_page , & decrypted ) ) {
return true ;
}
if ( page_type ! = FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED ) {
return buf_page_is_corrupted ( true , tmp_page , cursor - > zip_size , space ) ;
}
}
if ( page_type = = FIL_PAGE_PAGE_COMPRESSED ) {
memcpy ( tmp_page , page , cursor - > page_size ) ;
}
if ( page_type = = FIL_PAGE_PAGE_COMPRESSED | | page_type = = FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED ) {
ulint decomp = fil_page_decompress ( tmp_frame , tmp_page ) ;
page_type = mach_read_from_2 ( tmp_page + FIL_PAGE_TYPE ) ;
return ( ! decomp
| | ( decomp ! = srv_page_size & & cursor - > zip_size )
| | page_type = = FIL_PAGE_PAGE_COMPRESSED
| | page_type = = FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED
| | buf_page_is_corrupted ( true , tmp_page , cursor - > zip_size , space ) ) ;
}
return buf_page_is_corrupted ( true , page , cursor - > zip_size , space ) ;
}
/************************************************************************
Reads and verifies the next block of pages from the source
file . Positions the cursor after the last read non - corrupted page .
@ -284,8 +365,6 @@ xb_fil_cur_read(
xb_fil_cur_result_t ret ;
ib_int64_t offset ;
ib_int64_t to_read ;
byte tmp_frame [ UNIV_PAGE_SIZE_MAX ] ;
byte tmp_page [ UNIV_PAGE_SIZE_MAX ] ;
cursor - > read_filter - > get_next_batch ( & cursor - > read_filter_ctxt ,
& offset , & to_read ) ;
@ -347,78 +426,8 @@ read_retry:
for ( page = cursor - > buf , i = 0 ; i < npages ;
page + = cursor - > page_size , i + + ) {
ulint page_no = cursor - > buf_page_no + i ;
ulint page_type = mach_read_from_2 ( page + FIL_PAGE_TYPE ) ;
if ( cursor - > space_id = = TRX_SYS_SPACE
& & page_no > = FSP_EXTENT_SIZE
& & page_no < FSP_EXTENT_SIZE * 3 ) {
/* We ignore the doublewrite buffer pages */
} else if ( mach_read_from_4 ( page + FIL_PAGE_OFFSET ) ! = page_no
& & space - > id ! = TRX_SYS_SPACE ) {
/* On pages that are not all zero, the
page number must match .
There may be a mismatch on tablespace ID ,
because files may be renamed during backup .
We disable the page number check
on the system tablespace , because it may consist
of multiple files , and here we count the pages
from the start of each file . )
The first 38 and last 8 bytes are never encrypted . */
const ulint * p = reinterpret_cast < ulint * > ( page ) ;
const ulint * const end = reinterpret_cast < ulint * > (
page + cursor - > page_size ) ;
do {
if ( * p + + ) {
goto corrupted ;
}
} while ( p ! = end ) ;
} else if ( mach_read_from_4 (
page
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION )
& & space - > crypt_data
& & space - > crypt_data - > type
! = CRYPT_SCHEME_UNENCRYPTED
& & fil_space_verify_crypt_checksum (
page , cursor - > zip_size ) ) {
bool decrypted = false ;
memcpy ( tmp_page , page , cursor - > page_size ) ;
if ( ! fil_space_decrypt ( space , tmp_frame ,
tmp_page , & decrypted ) ) {
goto corrupted ;
}
if ( page_type = = FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED ) {
goto page_decomp ;
}
if ( buf_page_is_corrupted (
true , tmp_page , cursor - > zip_size , space ) ) {
goto corrupted ;
}
} else if ( page_type = = FIL_PAGE_PAGE_COMPRESSED ) {
memcpy ( tmp_page , page , cursor - > page_size ) ;
page_decomp :
ulint decomp = fil_page_decompress ( tmp_frame , tmp_page ) ;
page_type = mach_read_from_2 ( tmp_page + FIL_PAGE_TYPE ) ;
if ( ! decomp
| | ( decomp ! = srv_page_size & & cursor - > zip_size )
| | page_type = = FIL_PAGE_PAGE_COMPRESSED
| | page_type = = FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED
| | buf_page_is_corrupted ( true , tmp_page ,
cursor - > zip_size ,
space ) ) {
goto corrupted ;
}
} else if ( page_type = = FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED
| | buf_page_is_corrupted ( true , page ,
cursor - > zip_size , space ) ) {
corrupted :
if ( page_is_corrupted ( page , page_no , cursor , space ) ) {
retry_count - - ;
if ( retry_count = = 0 ) {