8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 22:43:04 +01:00

Fixed CORE-1127 : Circular index references in corrupt database causes fbserver to loop infinitely.

Thanks to Diane Downie
This commit is contained in:
hvlad 2007-02-14 08:58:07 +00:00
parent fbdbd4b450
commit e4b66b962e
3 changed files with 27 additions and 2 deletions

View File

@ -437,7 +437,8 @@ const int VAL_TIP_CONFUSED = 21;
const int VAL_REL_CHAIN_ORPHANS = 22;
const int VAL_INDEX_MISSING_ROWS = 23;
const int VAL_INDEX_ORPHAN_CHILD = 24;
const int VAL_MAX_ERROR = 25;
const int VAL_INDEX_CYCLE = 25;
const int VAL_MAX_ERROR = 26;
//

View File

@ -647,7 +647,8 @@ static const TEXT msg_table[][66] = {
"Transaction inventory pages confused, sequence %ld",
"Relation has %ld orphan backversions (%ld in use)",
"Index %d is corrupt (missing entries)",
"Index %d has orphan child page at page %ld"
"Index %d has orphan child page at page %ld",
"Index %d has a circular reference at page %ld"
};
@ -1430,11 +1431,16 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
SCHAR flags = 0;
UCHAR* pointer;
IndexNode node, lastNode;
PageBitmap visited_pages; // used to check circular page references, Diane Downie 2/9/07
while (next) {
WIN window(-1);
btree_page* page = 0;
fetch_page(tdbb, control, next, pag_index, &window, &page);
// remember each page for circular reference detection
visited_pages.set(next);
if ((next != page_number) &&
(page->btr_header.pag_flags & BTR_FLAG_COPY_MASK) !=
(flags & BTR_FLAG_COPY_MASK))
@ -1686,6 +1692,13 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
nullKeyHandled = !(unique && null_key);
}
// check for circular referenes
if (next && visited_pages.test(next))
{
corrupt(tdbb, control, VAL_INDEX_CYCLE, relation,
id + 1, next);
next = 0;
}
CCH_RELEASE(tdbb, &window);
}

View File

@ -768,6 +768,17 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource*
CCH_RELEASE(tdbb, &rpb->rpb_window);
return false;
}
// hvlad: if i'm garbage collector i don't need to read backversion of active
// record. Just do notify self about it (if background policy enabled)
if (attachment->att_flags & ATT_garbage_collector)
{
// VIO_chase_record_version
notify_garbage_collector(tdbb, rpb);
CCH_RELEASE(tdbb, &rpb->rpb_window);
return false;
}
if (!(rpb->rpb_flags & rpb_delta)) {
rpb->rpb_prior = NULL;
/* Fetch a back version. If a latch timeout occurs, refetch the