Commit a298dfb8 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-35053 Crash in purge_sys_t::iterator::free_history_rseg()

purge_sys_t::get_page(): Avoid accessing a freed reference to pages[id]
after pages.erase(id).  This heap-use-after-free would sometimes be
caught by AddressSanitizer.

purge_sys_t::iterator::free_history_rseg(): Do not crash if undo=nullptr
(the database is corrupted).

Reviewed by: Debarun Banerjee
parent 2d031f4a
......@@ -493,16 +493,18 @@ inline dberr_t purge_sys_t::iterator::free_history_rseg(trx_rseg_t &rseg) const
if (undo->hdr_page_no == hdr_addr.page)
goto found_cached;
ut_ad("inconsistent undo logs" == 0);
if (false)
found_cached:
UT_LIST_REMOVE(rseg.undo_cached, undo);
static_assert(FIL_NULL == 0xffffffff, "");
if (UNIV_UNLIKELY(mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT +
rseg_hdr->page.frame)))
trx_rseg_format_upgrade(rseg_hdr, &mtr);
if (UNIV_LIKELY(undo != nullptr))
{
UT_LIST_REMOVE(rseg.undo_cached, undo);
mtr.memset(rseg_hdr, TRX_RSEG + TRX_RSEG_UNDO_SLOTS +
undo->id * TRX_RSEG_SLOT_SIZE, 4, 0xff);
ut_free(undo);
}
mtr.write<8,mtr_t::MAYBE_NOP>(*rseg_hdr, TRX_RSEG + TRX_RSEG_MAX_TRX_ID +
rseg_hdr->page.frame,
trx_sys.get_max_trx_id() - 1);
......@@ -778,13 +780,16 @@ buf_block_t *purge_sys_t::get_page(page_id_t id)
{
ut_ad(!recv_sys.recovery_on);
buf_block_t*& undo_page= pages[id];
buf_block_t *&h= pages[id];
buf_block_t *undo_page= h;
if (!undo_page)
{
undo_page= buf_pool.page_fix(id); // batch_cleanup() will unfix()
if (!undo_page)
pages.erase(id);
else
h= undo_page;
}
return undo_page;
......
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