mirror of
https://github.com/MariaDB/server.git
synced 2025-04-18 21:44:20 +03:00
MDEV-36152 mariadb-backup --backup crash during innodb_undo_log_truncate=ON, innodb_encrypt_log=ON
recv_sys_t::parse(): Allocate decrypt_buf also for storing==BACKUP but limit its size to correspond to 1 byte of record payload. Ensure that last_offset=0 for storing==BACKUP. When parsing INIT_PAGE or FREE_PAGE, avoid an unnecessary l.copy_if_needed() for storing!=YES. When parsing EXTENDED in storing==BACKUP, properly invoke l.copy_if_needed() on a large enough decrypt_buf. When parsing WRITE, MEMMOVE, MEMSET in storing==BACKUP, skip further validation (and potential overflow of the tiny decrypt_buf), like we used to do before commit 46aaf328ce424aededdb61e59a48db05630563d5 (MDEV-35830). Reviewed by: Debarun Banerjee
This commit is contained in:
parent
0c204bfb87
commit
809a0cebdc
@ -2507,9 +2507,11 @@ restart:
|
||||
ut_ad(log_sys.is_latest());
|
||||
|
||||
alignas(8) byte iv[MY_AES_BLOCK_SIZE];
|
||||
byte *decrypt_buf= storing != BACKUP
|
||||
? static_cast<byte*>(alloca(srv_page_size)) : nullptr;
|
||||
|
||||
byte *decrypt_buf=
|
||||
static_cast<byte*>(alloca(storing == BACKUP
|
||||
? 1/*type,length*/ + 5/*space_id*/ +
|
||||
5/*page_no*/ + 1/*rlen*/
|
||||
: srv_page_size));
|
||||
const lsn_t start_lsn{lsn};
|
||||
|
||||
/* Check that the entire mini-transaction is included within the buffer */
|
||||
@ -2599,7 +2601,10 @@ restart:
|
||||
ut_d(std::set<page_id_t> modified);
|
||||
#endif
|
||||
|
||||
uint32_t space_id= 0, page_no= 0, last_offset= 0;
|
||||
uint32_t space_id= 0, page_no= 0;
|
||||
/* The end offset the last write (always 0 in storing==BACKUP).
|
||||
The value 1 means that no "same page" record is allowed. */
|
||||
uint last_offset= 0;
|
||||
bool got_page_op= false;
|
||||
|
||||
for (l= begin;; l+= rlen)
|
||||
@ -2712,8 +2717,7 @@ restart:
|
||||
{
|
||||
mach_write_to_4(iv + 8, space_id);
|
||||
mach_write_to_4(iv + 12, page_no);
|
||||
byte eb[1/*type,length*/ + 5/*space_id*/ + 5/*page_no*/ + 1/*rlen*/];
|
||||
if (*l.copy_if_needed(iv, eb, recs, 1) == TRIM_PAGES)
|
||||
if (*l.copy_if_needed(iv, decrypt_buf, recs, 1) == TRIM_PAGES)
|
||||
undo_space_trunc(space_id);
|
||||
}
|
||||
continue;
|
||||
@ -2762,10 +2766,10 @@ restart:
|
||||
case FREE_PAGE:
|
||||
ut_ad(freed.emplace(id).second);
|
||||
/* the next record must not be same_page */
|
||||
last_offset= 1;
|
||||
if (storing != BACKUP) last_offset= 1;
|
||||
goto free_or_init_page;
|
||||
case INIT_PAGE:
|
||||
last_offset= FIL_PAGE_TYPE;
|
||||
if (storing != BACKUP) last_offset= FIL_PAGE_TYPE;
|
||||
free_or_init_page:
|
||||
if (UNIV_UNLIKELY(rlen != 0))
|
||||
goto record_corrupted;
|
||||
@ -2797,7 +2801,8 @@ restart:
|
||||
erase(r);
|
||||
continue;
|
||||
}
|
||||
cl= l.copy_if_needed(iv, decrypt_buf, recs, rlen);
|
||||
if (storing == YES)
|
||||
cl= l.copy_if_needed(iv, decrypt_buf, recs, rlen);
|
||||
break;
|
||||
case EXTENDED:
|
||||
if (storing == NO)
|
||||
@ -2811,7 +2816,8 @@ restart:
|
||||
continue;
|
||||
if (UNIV_UNLIKELY(!rlen))
|
||||
goto record_corrupted;
|
||||
cl= l.copy_if_needed(iv, decrypt_buf, recs, rlen);
|
||||
if (storing == YES || rlen == 1)
|
||||
cl= l.copy_if_needed(iv, decrypt_buf, recs, rlen);
|
||||
if (rlen == 1 && *cl == TRIM_PAGES)
|
||||
{
|
||||
if (!srv_is_undo_tablespace(space_id) ||
|
||||
@ -2825,7 +2831,7 @@ restart:
|
||||
truncated_undo_spaces[space_id - srv_undo_space_id_start]=
|
||||
{ start_lsn, page_no };
|
||||
/* the next record must not be same_page */
|
||||
last_offset= 1;
|
||||
if (storing != BACKUP) last_offset= 1;
|
||||
if (undo_space_trunc)
|
||||
undo_space_trunc(space_id);
|
||||
continue;
|
||||
@ -2833,7 +2839,7 @@ restart:
|
||||
/* This record applies to an undo log or index page, and it
|
||||
may be followed by subsequent WRITE or similar records for the
|
||||
same page in the same mini-transaction. */
|
||||
last_offset= FIL_PAGE_TYPE;
|
||||
if (storing != BACKUP) last_offset= FIL_PAGE_TYPE;
|
||||
break;
|
||||
case OPTION:
|
||||
/* OPTION records can be safely ignored in recovery */
|
||||
@ -2850,6 +2856,8 @@ restart:
|
||||
case WRITE:
|
||||
case MEMMOVE:
|
||||
case MEMSET:
|
||||
if (storing == BACKUP)
|
||||
continue;
|
||||
if (storing == NO && UNIV_LIKELY(page_no != 0))
|
||||
/* fil_space_set_recv_size_and_flags() is mandatory for storing==NO.
|
||||
It is only applicable to page_no == 0. Other than that, we can just
|
||||
|
Loading…
x
Reference in New Issue
Block a user