Skip to content

Commit 809a0ce

Browse files
committed
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 46aaf32 (MDEV-35830). Reviewed by: Debarun Banerjee
1 parent 0c204bf commit 809a0ce

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

storage/innobase/log/log0recv.cc

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,9 +2507,11 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
25072507
ut_ad(log_sys.is_latest());
25082508

25092509
alignas(8) byte iv[MY_AES_BLOCK_SIZE];
2510-
byte *decrypt_buf= storing != BACKUP
2511-
? static_cast<byte*>(alloca(srv_page_size)) : nullptr;
2512-
2510+
byte *decrypt_buf=
2511+
static_cast<byte*>(alloca(storing == BACKUP
2512+
? 1/*type,length*/ + 5/*space_id*/ +
2513+
5/*page_no*/ + 1/*rlen*/
2514+
: srv_page_size));
25132515
const lsn_t start_lsn{lsn};
25142516

25152517
/* Check that the entire mini-transaction is included within the buffer */
@@ -2599,7 +2601,10 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
25992601
ut_d(std::set<page_id_t> modified);
26002602
#endif
26012603

2602-
uint32_t space_id= 0, page_no= 0, last_offset= 0;
2604+
uint32_t space_id= 0, page_no= 0;
2605+
/* The end offset the last write (always 0 in storing==BACKUP).
2606+
The value 1 means that no "same page" record is allowed. */
2607+
uint last_offset= 0;
26032608
bool got_page_op= false;
26042609

26052610
for (l= begin;; l+= rlen)
@@ -2712,8 +2717,7 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
27122717
{
27132718
mach_write_to_4(iv + 8, space_id);
27142719
mach_write_to_4(iv + 12, page_no);
2715-
byte eb[1/*type,length*/ + 5/*space_id*/ + 5/*page_no*/ + 1/*rlen*/];
2716-
if (*l.copy_if_needed(iv, eb, recs, 1) == TRIM_PAGES)
2720+
if (*l.copy_if_needed(iv, decrypt_buf, recs, 1) == TRIM_PAGES)
27172721
undo_space_trunc(space_id);
27182722
}
27192723
continue;
@@ -2762,10 +2766,10 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
27622766
case FREE_PAGE:
27632767
ut_ad(freed.emplace(id).second);
27642768
/* the next record must not be same_page */
2765-
last_offset= 1;
2769+
if (storing != BACKUP) last_offset= 1;
27662770
goto free_or_init_page;
27672771
case INIT_PAGE:
2768-
last_offset= FIL_PAGE_TYPE;
2772+
if (storing != BACKUP) last_offset= FIL_PAGE_TYPE;
27692773
free_or_init_page:
27702774
if (UNIV_UNLIKELY(rlen != 0))
27712775
goto record_corrupted;
@@ -2797,7 +2801,8 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
27972801
erase(r);
27982802
continue;
27992803
}
2800-
cl= l.copy_if_needed(iv, decrypt_buf, recs, rlen);
2804+
if (storing == YES)
2805+
cl= l.copy_if_needed(iv, decrypt_buf, recs, rlen);
28012806
break;
28022807
case EXTENDED:
28032808
if (storing == NO)
@@ -2811,7 +2816,8 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
28112816
continue;
28122817
if (UNIV_UNLIKELY(!rlen))
28132818
goto record_corrupted;
2814-
cl= l.copy_if_needed(iv, decrypt_buf, recs, rlen);
2819+
if (storing == YES || rlen == 1)
2820+
cl= l.copy_if_needed(iv, decrypt_buf, recs, rlen);
28152821
if (rlen == 1 && *cl == TRIM_PAGES)
28162822
{
28172823
if (!srv_is_undo_tablespace(space_id) ||
@@ -2825,15 +2831,15 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
28252831
truncated_undo_spaces[space_id - srv_undo_space_id_start]=
28262832
{ start_lsn, page_no };
28272833
/* the next record must not be same_page */
2828-
last_offset= 1;
2834+
if (storing != BACKUP) last_offset= 1;
28292835
if (undo_space_trunc)
28302836
undo_space_trunc(space_id);
28312837
continue;
28322838
}
28332839
/* This record applies to an undo log or index page, and it
28342840
may be followed by subsequent WRITE or similar records for the
28352841
same page in the same mini-transaction. */
2836-
last_offset= FIL_PAGE_TYPE;
2842+
if (storing != BACKUP) last_offset= FIL_PAGE_TYPE;
28372843
break;
28382844
case OPTION:
28392845
/* OPTION records can be safely ignored in recovery */
@@ -2850,6 +2856,8 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
28502856
case WRITE:
28512857
case MEMMOVE:
28522858
case MEMSET:
2859+
if (storing == BACKUP)
2860+
continue;
28532861
if (storing == NO && UNIV_LIKELY(page_no != 0))
28542862
/* fil_space_set_recv_size_and_flags() is mandatory for storing==NO.
28552863
It is only applicable to page_no == 0. Other than that, we can just

0 commit comments

Comments
 (0)