Skip to content

Commit 98fadc5

Browse files
committed
Backported postfix for CORE-6528: added control for some other page types only after reading page from disk
1 parent 0656331 commit 98fadc5

2 files changed

Lines changed: 131 additions & 46 deletions

File tree

src/jrd/btr.cpp

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4062,36 +4062,7 @@ static index_root_page* fetch_root(thread_db* tdbb, WIN* window, const jrd_rel*
40624062
window->win_page = relPages->rel_index_root;
40634063
}
40644064

4065-
index_root_page* irp = (index_root_page*) CCH_FETCH(tdbb, window, LCK_read, pag_root);
4066-
if (irp)
4067-
{
4068-
// check RPT size correctness
4069-
FB_UINT64 rptSize = sizeof(index_root_page) - sizeof(index_root_page::irt_repeat);
4070-
rptSize += FB_UINT64(irp->irt_count) * sizeof(index_root_page::irt_repeat);
4071-
if (rptSize > tdbb->getDatabase()->dbb_page_size)
4072-
{
4073-
CCH_RELEASE(tdbb, window);
4074-
(Arg::Gds(isc_random) << "Bad index root page: too many indices").raise();
4075-
}
4076-
4077-
// check keys location on page
4078-
for (USHORT i = 0; i < irp->irt_count; ++i)
4079-
{
4080-
index_root_page::irt_repeat* irt = &irp->irt_rpt[i];
4081-
if (!irt->getRoot())
4082-
continue;
4083-
4084-
FB_UINT64 descEnd = irt->irt_desc;
4085-
descEnd += FB_UINT64(irt->irt_keys) * sizeof(irtd);
4086-
if (descEnd > tdbb->getDatabase()->dbb_page_size)
4087-
{
4088-
CCH_RELEASE(tdbb, window);
4089-
(Arg::Gds(isc_random) << "Bad index root page: keys run out of page").raise();
4090-
}
4091-
}
4092-
}
4093-
4094-
return irp;
4065+
return (index_root_page*) CCH_FETCH(tdbb, window, LCK_read, pag_root);
40954066
}
40964067

40974068

src/jrd/cch.cpp

Lines changed: 130 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ static LatchState latch_buffer(thread_db*, Sync&, BufferDesc*, const PageNumber,
138138
static LockState lock_buffer(thread_db*, BufferDesc*, const SSHORT, const SCHAR);
139139
static ULONG memory_init(thread_db*, BufferControl*, SLONG);
140140
static void page_validation_error(thread_db*, win*, SSHORT);
141+
inline void page_validate(thread_db*, win*, const LockState, SSHORT);
142+
static void validate_read_page(thread_db*, win*, SSHORT);
141143
static void purgePrecedence(BufferControl*, BufferDesc*);
142144
static SSHORT related(BufferDesc*, const BufferDesc*, SSHORT, const ULONG);
143145
static bool writeable(BufferDesc*);
@@ -747,10 +749,7 @@ pag* CCH_fetch(thread_db* tdbb, WIN* window, int lock_type, SCHAR page_type, int
747749

748750
adjust_scan_count(window, lockState == lsLocked);
749751

750-
// Validate the fetched page matches the expected type
751-
752-
if (bdb->bdb_buffer->pag_type != page_type && page_type != pag_undefined)
753-
page_validation_error(tdbb, window, page_type);
752+
page_validate(tdbb, window, lockState, page_type);
754753

755754
return window->win_buffer;
756755
}
@@ -1412,10 +1411,7 @@ pag* CCH_handoff(thread_db* tdbb, WIN* window, ULONG page, int lock, SCHAR page_
14121411

14131412
adjust_scan_count(window, must_read == lsLocked);
14141413

1415-
// Validate the fetched page matches the expected type
1416-
1417-
if (bdb->bdb_buffer->pag_type != page_type && page_type != pag_undefined)
1418-
page_validation_error(tdbb, window, page_type);
1414+
page_validate(tdbb, window, must_read, page_type);
14191415

14201416
return window->win_buffer;
14211417
}
@@ -4357,7 +4353,7 @@ static ULONG memory_init(thread_db* tdbb, BufferControl* bcb, SLONG number)
43574353
}
43584354

43594355

4360-
static void page_validation_error(thread_db* tdbb, WIN* window, SSHORT type)
4356+
static void page_validation_error(thread_db* tdbb, WIN* window, SSHORT type, Arg::StatusVector& err)
43614357
{
43624358
/**************************************
43634359
*
@@ -4376,22 +4372,140 @@ static void page_validation_error(thread_db* tdbb, WIN* window, SSHORT type)
43764372
**************************************/
43774373
SET_TDBB(tdbb);
43784374
BufferDesc* bdb = window->win_bdb;
4379-
const pag* page = bdb->bdb_buffer;
4380-
43814375
PageSpace* pages =
43824376
tdbb->getDatabase()->dbb_page_manager.findPageSpace(bdb->bdb_page.getPageSpaceID());
43834377

43844378
ERR_build_status(tdbb->tdbb_status_vector,
4385-
Arg::Gds(isc_db_corrupt) << Arg::Str(pages->file->fil_string) <<
4386-
Arg::Gds(isc_page_type_err) <<
4387-
Arg::Gds(isc_badpagtyp) << Arg::Num(bdb->bdb_page.getPageNum()) <<
4388-
pagtype(type) <<
4389-
pagtype(page->pag_type));
4379+
Arg::Gds(isc_db_corrupt) << Arg::Str(pages->file->fil_string) << err);
4380+
43904381
// We should invalidate this bad buffer.
43914382
CCH_unwind(tdbb, true);
43924383
}
43934384

43944385

4386+
inline void page_validate(thread_db* tdbb, WIN* window, const LockState ls, SSHORT type)
4387+
{
4388+
// Validate only when required page type is known and page was read from disk
4389+
// if (type != pag_undefined && ls == lsLocked)
4390+
// validate_read_page(tdbb, window, type);
4391+
}
4392+
4393+
4394+
static void validate_read_page(thread_db* tdbb, WIN* window, SSHORT type)
4395+
{
4396+
// Validate the fetched page matches the expected type
4397+
if (window->win_buffer->pag_type != type)
4398+
{
4399+
BufferDesc* bdb = window->win_bdb;
4400+
const pag* page = bdb->bdb_buffer;
4401+
4402+
page_validation_error(tdbb, window, type,
4403+
Arg::Gds(isc_page_type_err) <<
4404+
Arg::Gds(isc_badpagtyp) << Arg::Num(bdb->bdb_page.getPageNum()) << pagtype(type) << pagtype(page->pag_type));
4405+
}
4406+
4407+
switch(type)
4408+
{
4409+
case pag_root:
4410+
{
4411+
index_root_page* pg = (index_root_page*) window->win_buffer;
4412+
4413+
// check RPT size correctness
4414+
FB_UINT64 rptSize = sizeof(index_root_page) - sizeof(index_root_page::irt_repeat);
4415+
rptSize += FB_UINT64(pg->irt_count) * sizeof(index_root_page::irt_repeat);
4416+
if (rptSize > tdbb->getDatabase()->dbb_page_size)
4417+
{
4418+
page_validation_error(tdbb, window, type,
4419+
Arg::Gds(isc_random) << "Bad index root page: too many indices");
4420+
}
4421+
4422+
// check keys location on page
4423+
for (USHORT i = 0; i < pg->irt_count; ++i)
4424+
{
4425+
index_root_page::irt_repeat* rpt = &pg->irt_rpt[i];
4426+
if (!rpt->getRoot())
4427+
continue;
4428+
4429+
FB_UINT64 descEnd = rpt->irt_desc;
4430+
descEnd += FB_UINT64(rpt->irt_keys) * sizeof(irtd);
4431+
if (descEnd > tdbb->getDatabase()->dbb_page_size)
4432+
{
4433+
page_validation_error(tdbb, window, type,
4434+
Arg::Gds(isc_random) << "Bad index root page: keys run out of page");
4435+
}
4436+
}
4437+
4438+
break;
4439+
}
4440+
4441+
case pag_blob:
4442+
{
4443+
blob_page* pg = (blob_page*) window->win_buffer;
4444+
4445+
// check used space size correctness
4446+
FB_UINT64 usedSpace = sizeof(blob_page) - sizeof(blob_page::blp_page);
4447+
usedSpace += FB_UINT64(pg->blp_length);
4448+
if (usedSpace > tdbb->getDatabase()->dbb_page_size)
4449+
{
4450+
page_validation_error(tdbb, window, type,
4451+
Arg::Gds(isc_random) << "Bad blob page: data does not fit on page");
4452+
}
4453+
4454+
break;
4455+
}
4456+
4457+
case pag_data:
4458+
{
4459+
data_page* pg = (data_page*) window->win_buffer;
4460+
4461+
// check RPT size correctness
4462+
FB_UINT64 rptSize = sizeof(data_page) - sizeof(data_page::dpg_repeat);
4463+
rptSize += FB_UINT64(pg->dpg_count) * sizeof(data_page::dpg_repeat);
4464+
if (rptSize > tdbb->getDatabase()->dbb_page_size)
4465+
{
4466+
page_validation_error(tdbb, window, type,
4467+
Arg::Gds(isc_random) << "Bad data page: too many record fragments");
4468+
}
4469+
4470+
// check fragments location on page
4471+
for (USHORT i = 0; i < pg->dpg_count; ++i)
4472+
{
4473+
data_page::dpg_repeat* rpt = &pg->dpg_rpt[i];
4474+
if (!(rpt->dpg_offset && rpt->dpg_length))
4475+
continue;
4476+
4477+
FB_UINT64 fragEnd = rpt->dpg_offset;
4478+
fragEnd += rpt->dpg_length;
4479+
if (fragEnd > tdbb->getDatabase()->dbb_page_size)
4480+
{
4481+
page_validation_error(tdbb, window, type,
4482+
Arg::Gds(isc_random) << "Bad data page: record fragment runs out of page");
4483+
}
4484+
}
4485+
4486+
break;
4487+
}
4488+
4489+
case pag_pointer:
4490+
{
4491+
pointer_page* pg = (pointer_page*) window->win_buffer;
4492+
4493+
// check used space size correctness
4494+
FB_UINT64 usedSpace = sizeof(pointer_page) - sizeof(pointer_page::ppg_page);
4495+
usedSpace += FB_UINT64(pg->ppg_count) * sizeof(pointer_page::ppg_page);
4496+
if (usedSpace > tdbb->getDatabase()->dbb_page_size)
4497+
{
4498+
page_validation_error(tdbb, window, type,
4499+
Arg::Gds(isc_random) << "Bad pointer page: data page vector does not fit on page");
4500+
}
4501+
4502+
break;
4503+
}
4504+
4505+
}
4506+
}
4507+
4508+
43954509
#ifdef CACHE_READER
43964510
static void prefetch_epilogue(Prefetch* prefetch, FbStatusVector* status_vector)
43974511
{

0 commit comments

Comments
 (0)