Skip to content

Commit 8597483

Browse files
committed
Fixed potential endless loop inside MET_scan_relation: when relation is system-defined and its ODS is greater than ODS of current database.
Thanks to @dyemanov for pointing into this.
1 parent b103e8f commit 8597483

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

src/jrd/met.epp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ static int blocking_ast_relation(void*);
115115
static int partners_ast_relation(void*);
116116
static int rescan_ast_relation(void*);
117117
static ULONG get_rel_flags_from_FLAGS(USHORT);
118+
static USHORT get_sysrel_ods(jrd_rel*);
118119
static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, TrigVector**, const TEXT*, FB_UINT64, SSHORT,
119120
USHORT, const MetaName&, const string&, const bid*, Nullable<bool> ssDefiner);
120121
static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*);
@@ -4095,9 +4096,13 @@ static void scan_relation(thread_db* tdbb, jrd_rel* relation)
40954096
AutoCacheRequest request(tdbb, irq_r_fields, IRQ_REQUESTS);
40964097
CompilerScratch* csb = NULL;
40974098

4099+
bool found = false;
4100+
40984101
FOR(REQUEST_HANDLE request)
40994102
REL IN RDB$RELATIONS WITH REL.RDB$RELATION_ID EQ relation->rel_id
41004103
{
4104+
found = true;
4105+
41014106
// Pick up relation level stuff
41024107
relation->rel_current_fmt = REL.RDB$FORMAT;
41034108
vec<jrd_fld*>* vector = relation->rel_fields =
@@ -4371,6 +4376,30 @@ static void scan_relation(thread_db* tdbb, jrd_rel* relation)
43714376

43724377
delete csb;
43734378

4379+
if (!found && !(relation->rel_flags & REL_scanned))
4380+
{
4381+
// Relation was not found in RDB$RELATIONS. It could be system relation
4382+
// defined in INI for latest supported ODS while database is in older ODS.
4383+
4384+
const USHORT dbbOds = ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_version);
4385+
4386+
if (relation->isSystem() && dbbOds < ODS_CURRENT_VERSION &&
4387+
dbbOds < get_sysrel_ods(relation))
4388+
{
4389+
relation->rel_flags |= REL_scanned;
4390+
}
4391+
else
4392+
{
4393+
fb_assert(false);
4394+
4395+
string name(relation->rel_name);
4396+
if (name.isEmpty())
4397+
name.printf("<ID = %u>", relation->rel_id);
4398+
4399+
ERR_post(Arg::Gds(isc_relnotdef) << Arg::Str(name));
4400+
}
4401+
}
4402+
43744403
// We have just loaded the triggers onto the local vector triggers.
43754404
// It's now time to place them at their rightful place inside the relation block.
43764405

@@ -4776,6 +4805,37 @@ ULONG MET_get_rel_flags_from_TYPE(USHORT type)
47764805
}
47774806

47784807

4808+
// Search system-defined list for given relation and return its ODS.
4809+
// Return zero, if not found.
4810+
static USHORT get_sysrel_ods(jrd_rel* relation)
4811+
{
4812+
if (relation->rel_id >= rel_MAX)
4813+
return 0;
4814+
4815+
#define RELATION(name, id, ods, type) id, ods,
4816+
#define FIELD(symbol, name, id, update, ods)
4817+
#define END_RELATION
4818+
4819+
static const int rels[] =
4820+
{
4821+
#include "../jrd/relations.h"
4822+
0, 0
4823+
};
4824+
4825+
#undef RELATION
4826+
#undef FIELD
4827+
#undef END_RELATION
4828+
4829+
for (int n = 0; n < FB_NELEM(rels); n += 2)
4830+
{
4831+
if (relation->rel_id == rels[n])
4832+
return rels[n + 1];
4833+
}
4834+
4835+
return 0;
4836+
}
4837+
4838+
47794839
static void get_trigger(thread_db* tdbb, jrd_rel* relation,
47804840
bid* blob_id, bid* debug_blob_id, TrigVector** ptr,
47814841
const TEXT* name, FB_UINT64 type,

0 commit comments

Comments
 (0)