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

Report InnoDB redo log corruption better

recv_parse_log_recs(): Check for corruption before checking for
end-of-log-buffer.

mlog_parse_initial_log_record(), page_cur_parse_delete_rec():
Flag corruption for out-of-bounds values, and let the caller
dump the corrupted redo log extract.
parent 0e15ae16
...@@ -2251,7 +2251,6 @@ recv_parse_log_rec( ...@@ -2251,7 +2251,6 @@ recv_parse_log_rec(
*type, new_ptr, end_ptr, *space, *page_no, apply, NULL, NULL); *type, new_ptr, end_ptr, *space, *page_no, apply, NULL, NULL);
if (UNIV_UNLIKELY(new_ptr == NULL)) { if (UNIV_UNLIKELY(new_ptr == NULL)) {
return(0); return(0);
} }
...@@ -2402,13 +2401,8 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply) ...@@ -2402,13 +2401,8 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply)
len = recv_parse_log_rec(&type, ptr, end_ptr, &space, len = recv_parse_log_rec(&type, ptr, end_ptr, &space,
&page_no, apply, &body); &page_no, apply, &body);
if (len == 0) {
return(false);
}
if (recv_sys->found_corrupt_log) { if (recv_sys->found_corrupt_log) {
recv_report_corrupt_log( recv_report_corrupt_log(ptr, type, space, page_no);
ptr, type, space, page_no);
return(true); return(true);
} }
...@@ -2416,6 +2410,10 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply) ...@@ -2416,6 +2410,10 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply)
return(true); return(true);
} }
if (len == 0) {
return(false);
}
new_recovered_lsn = recv_calc_lsn_on_data_add(old_lsn, len); new_recovered_lsn = recv_calc_lsn_on_data_add(old_lsn, len);
if (new_recovered_lsn > recv_sys->scanned_lsn) { if (new_recovered_lsn > recv_sys->scanned_lsn) {
...@@ -2542,10 +2540,6 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply) ...@@ -2542,10 +2540,6 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply)
&type, ptr, end_ptr, &space, &page_no, &type, ptr, end_ptr, &space, &page_no,
false, &body); false, &body);
if (len == 0) {
return(false);
}
if (recv_sys->found_corrupt_log if (recv_sys->found_corrupt_log
|| type == MLOG_CHECKPOINT || type == MLOG_CHECKPOINT
|| (*ptr & MLOG_SINGLE_REC_FLAG)) { || (*ptr & MLOG_SINGLE_REC_FLAG)) {
...@@ -2559,6 +2553,10 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply) ...@@ -2559,6 +2553,10 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply)
return(true); return(true);
} }
if (len == 0) {
return(false);
}
recv_previous_parsed_rec_type = type; recv_previous_parsed_rec_type = type;
recv_previous_parsed_rec_offset recv_previous_parsed_rec_offset
= recv_sys->recovered_offset + total_len; = recv_sys->recovered_offset + total_len;
......
...@@ -98,7 +98,11 @@ mlog_parse_initial_log_record( ...@@ -98,7 +98,11 @@ mlog_parse_initial_log_record(
} }
*type = mlog_id_t(*ptr & ~MLOG_SINGLE_REC_FLAG); *type = mlog_id_t(*ptr & ~MLOG_SINGLE_REC_FLAG);
ut_ad(*type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(*type)); if (UNIV_UNLIKELY(*type > MLOG_BIGGEST_TYPE
&& !EXTRA_CHECK_MLOG_NUMBER(*type))) {
recv_sys->found_corrupt_log = true;
return NULL;
}
ptr++; ptr++;
......
...@@ -2250,7 +2250,10 @@ page_cur_parse_delete_rec( ...@@ -2250,7 +2250,10 @@ page_cur_parse_delete_rec(
offset = mach_read_from_2(ptr); offset = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
ut_a(offset <= UNIV_PAGE_SIZE); if (UNIV_UNLIKELY(offset >= srv_page_size)) {
recv_sys->found_corrupt_log = true;
return NULL;
}
if (block) { if (block) {
page_t* page = buf_block_get_frame(block); page_t* page = buf_block_get_frame(block);
......
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