Skip to content

Commit 81c563d

Browse files
committed
Postfix for CORE-6528: added control for some other page types only after reading page from disk
1 parent 005bc68 commit 81c563d

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
@@ -4119,36 +4119,7 @@ static index_root_page* fetch_root(thread_db* tdbb, WIN* window, const jrd_rel*
41194119
window->win_page = relPages->rel_index_root;
41204120
}
41214121

4122-
index_root_page* irp = (index_root_page*) CCH_FETCH(tdbb, window, LCK_read, pag_root);
4123-
if (irp)
4124-
{
4125-
// check RPT size correctness
4126-
FB_UINT64 rptSize = sizeof(index_root_page) - sizeof(index_root_page::irt_repeat);
4127-
rptSize += FB_UINT64(irp->irt_count) * sizeof(index_root_page::irt_repeat);
4128-
if (rptSize > tdbb->getDatabase()->dbb_page_size)
4129-
{
4130-
CCH_RELEASE(tdbb, window);
4131-
(Arg::Gds(isc_random) << "Bad index root page: too many indices").raise();
4132-
}
4133-
4134-
// check keys location on page
4135-
for (USHORT i = 0; i < irp->irt_count; ++i)
4136-
{
4137-
index_root_page::irt_repeat* irt = &irp->irt_rpt[i];
4138-
if (!irt->getRoot())
4139-
continue;
4140-
4141-
FB_UINT64 descEnd = irt->irt_desc;
4142-
descEnd += FB_UINT64(irt->irt_keys) * sizeof(irtd);
4143-
if (descEnd > tdbb->getDatabase()->dbb_page_size)
4144-
{
4145-
CCH_RELEASE(tdbb, window);
4146-
(Arg::Gds(isc_random) << "Bad index root page: keys run out of page").raise();
4147-
}
4148-
}
4149-
}
4150-
4151-
return irp;
4122+
return (index_root_page*) CCH_FETCH(tdbb, window, LCK_read, pag_root);
41524123
}
41534124

41544125

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*);
@@ -748,10 +750,7 @@ pag* CCH_fetch(thread_db* tdbb, WIN* window, int lock_type, SCHAR page_type, int
748750

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

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

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

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

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

14211417
return window->win_buffer;
14221418
}
@@ -4364,7 +4360,7 @@ static ULONG memory_init(thread_db* tdbb, BufferControl* bcb, SLONG number)
43644360
}
43654361

43664362

4367-
static void page_validation_error(thread_db* tdbb, WIN* window, SSHORT type)
4363+
static void page_validation_error(thread_db* tdbb, WIN* window, SSHORT type, Arg::StatusVector& err)
43684364
{
43694365
/**************************************
43704366
*
@@ -4383,22 +4379,140 @@ static void page_validation_error(thread_db* tdbb, WIN* window, SSHORT type)
43834379
**************************************/
43844380
SET_TDBB(tdbb);
43854381
BufferDesc* bdb = window->win_bdb;
4386-
const pag* page = bdb->bdb_buffer;
4387-
43884382
PageSpace* pages =
43894383
tdbb->getDatabase()->dbb_page_manager.findPageSpace(bdb->bdb_page.getPageSpaceID());
43904384

43914385
ERR_build_status(tdbb->tdbb_status_vector,
4392-
Arg::Gds(isc_db_corrupt) << Arg::Str(pages->file->fil_string) <<
4393-
Arg::Gds(isc_page_type_err) <<
4394-
Arg::Gds(isc_badpagtyp) << Arg::Num(bdb->bdb_page.getPageNum()) <<
4395-
pagtype(type) <<
4396-
pagtype(page->pag_type));
4386+
Arg::Gds(isc_db_corrupt) << Arg::Str(pages->file->fil_string) << err);
4387+
43974388
// We should invalidate this bad buffer.
43984389
CCH_unwind(tdbb, true);
43994390
}
44004391

44014392

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

0 commit comments

Comments
 (0)