Skip to content

Commit 1755613

Browse files
committed
Fixed #8429: Segfault when already destroyed callback interface is used
(cherry picked from commit 658abd2)
1 parent a92f352 commit 1755613

File tree

15 files changed

+573
-27
lines changed

15 files changed

+573
-27
lines changed

doc/Using_OO_API.html

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3615,13 +3615,24 @@ <h1><font size="4" style="font-size: 14pt">Database encryption
36153615
is passed in both directions. The source of a key receives
36163616
dataLength bytes of data and may send up to bufferLength bytes into
36173617
buffer returning actual number of bytes placed into buffer.</font></p>
3618+
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">
3619+
int getHashLength(StatusType* status) - returns length of hash of the keys provided by interface.
3620+
Hash is needed to let caller compare interfaces for equality. Empty (no keys)
3621+
interface should return hash length equal to zero.
3622+
</font></p>
3623+
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">
3624+
void getHashData(StatusType* status, void* hash) - places hash of the keys provided by interface
3625+
into memory location defined by parameter <i>hash</i>. Should copy exact number of bytes
3626+
returned by getHashLength() call. Hash algorithm is chosen by plugin author
3627+
(in year 2024 SHA256 appears reasonable choice).
3628+
</font></p>
36183629
</ol>
36193630
<p style="margin-bottom: 0cm"><br/>
36203631

36213632
</p>
36223633
<p style="margin-bottom: 0cm"><a name="DbCryptInfo"></a><font size="4" style="font-size: 14pt">DbCryptInfo
36233634
interface is passed to DbCryptPlugin by engine. Plugin may save this
3624-
interface and use when needed to obtain additional informatio about
3635+
interface and use when needed to obtain additional information about
36253636
database.</font></p>
36263637
<ol>
36273638
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const

examples/dbcrypt/CryptApplication.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,28 @@ class CryptKey : public ICryptKeyCallbackImpl<CryptKey, CheckStatusWrapper>
3636
{
3737
if (length > 0 && buffer)
3838
{
39-
char k = 0x5a;
4039
memcpy(buffer, &k, 1);
4140
fprintf(stderr, "\nTransfered key to server\n");
4241
}
4342
return 1;
4443
}
44+
45+
int getHashLength(Firebird::CheckStatusWrapper* status) override
46+
{
47+
return 1;
48+
}
49+
50+
void getHashData(Firebird::CheckStatusWrapper* status, void* h) override
51+
{
52+
memcpy(h, &k, 1);
53+
}
54+
55+
private:
56+
static const char k;
4557
};
4658

59+
const char CryptKey::k = 0x5a;
60+
4761
class App
4862
{
4963
public:

examples/dbcrypt/CryptKeyHolder.cpp

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
6969
public:
7070
explicit CryptKeyHolder(IPluginConfig* cnf) throw()
7171
: callbackInterface(this), named(NULL), tempStatus(master->getStatus()),
72-
config(cnf), key(0), owner(NULL)
72+
config(cnf), key(0), init(false), owner(NULL)
7373
{
7474
config->addRef();
7575
}
@@ -110,10 +110,13 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
110110
return owner;
111111
}
112112

113-
ISC_UCHAR getKey()
113+
const ISC_UCHAR& getKey()
114114
{
115-
if (!key)
115+
if (!init)
116+
{
116117
keyCallback(&tempStatus, NULL);
118+
init = true;
119+
}
117120

118121
return key;
119122
}
@@ -139,7 +142,7 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
139142

140143
unsigned int callback(unsigned int, const void*, unsigned int length, void* buffer)
141144
{
142-
ISC_UCHAR k = holder->getKey();
145+
const ISC_UCHAR& k = holder->getKey();
143146
if (!k)
144147
{
145148
return 0;
@@ -152,6 +155,36 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
152155
return 1;
153156
}
154157

158+
int getHashLength(Firebird::CheckStatusWrapper* status) override
159+
{
160+
const ISC_UCHAR& k = holder->getKey();
161+
if (!k)
162+
{
163+
ISC_STATUS err[] = {isc_arg_gds, isc_wish_list};
164+
status->setErrors2(2, err);
165+
166+
return -1;
167+
}
168+
169+
return 1;
170+
}
171+
172+
void getHashData(Firebird::CheckStatusWrapper* status, void* h) override
173+
{
174+
// here key value is returned by hash function as is
175+
// do not do it in production - use some hash function
176+
const ISC_UCHAR& k = holder->getKey();
177+
if (!k)
178+
{
179+
ISC_STATUS err[] = {isc_arg_gds, isc_wish_list};
180+
status->setErrors2(2, err);
181+
182+
return;
183+
}
184+
185+
memcpy(h, &k, 1);
186+
}
187+
155188
private:
156189
CryptKeyHolder* holder;
157190
};
@@ -172,6 +205,18 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
172205
return 1;
173206
}
174207

208+
int getHashLength(Firebird::CheckStatusWrapper* status) override
209+
{
210+
return 1;
211+
}
212+
213+
void getHashData(Firebird::CheckStatusWrapper* status, void* h) override
214+
{
215+
// here key value is returned by hash function as is
216+
// do not do it in production - use some hash function
217+
memcpy(h, &key, 1);
218+
}
219+
175220
~NamedCallback()
176221
{
177222
delete next;
@@ -188,6 +233,7 @@ class CryptKeyHolder : public IKeyHolderPluginImpl<CryptKeyHolder, CheckStatusWr
188233

189234
IPluginConfig* config;
190235
ISC_UCHAR key;
236+
bool init;
191237

192238
FbSampleAtomic refCounter;
193239
IReferenceCounted* owner;

src/include/firebird/FirebirdInterface.idl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,23 @@ interface CryptKeyCallback : Versioned
941941
// any further details.
942942
uint callback(uint dataLength, const void* data,
943943
uint bufferLength, void* buffer);
944+
945+
version: // 6.0, 5.0.2, 4.0.6
946+
947+
// NULL in attStatus means attach was successful.
948+
// DO_RETRY return will be ignored in this case, but plugin has a chance
949+
// to reflect internally success.
950+
[stub defaultAction]
951+
void dummy1(Status status);
952+
953+
// interface not needed any more
954+
[stub defaultAction]
955+
void dummy2();
956+
957+
// Produce something to be compared with other interface instance
958+
[notImplemented(-1)]
959+
int getHashLength(Status status);
960+
void getHashData(Status status, void* hash);
944961
}
945962

946963

src/include/firebird/IdlFbInterfaces.h

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3891,14 +3891,18 @@ namespace Firebird
38913891
}
38923892
};
38933893

3894-
#define FIREBIRD_ICRYPT_KEY_CALLBACK_VERSION 2u
3894+
#define FIREBIRD_ICRYPT_KEY_CALLBACK_VERSION 3u
38953895

38963896
class ICryptKeyCallback : public IVersioned
38973897
{
38983898
public:
38993899
struct VTable : public IVersioned::VTable
39003900
{
39013901
unsigned (CLOOP_CARG *callback)(ICryptKeyCallback* self, unsigned dataLength, const void* data, unsigned bufferLength, void* buffer) CLOOP_NOEXCEPT;
3902+
void (CLOOP_CARG *dummy1)(ICryptKeyCallback* self, IStatus* status) CLOOP_NOEXCEPT;
3903+
void (CLOOP_CARG *dummy2)(ICryptKeyCallback* self) CLOOP_NOEXCEPT;
3904+
int (CLOOP_CARG *getHashLength)(ICryptKeyCallback* self, IStatus* status) CLOOP_NOEXCEPT;
3905+
void (CLOOP_CARG *getHashData)(ICryptKeyCallback* self, IStatus* status, void* hash) CLOOP_NOEXCEPT;
39023906
};
39033907

39043908
protected:
@@ -3919,6 +3923,55 @@ namespace Firebird
39193923
unsigned ret = static_cast<VTable*>(this->cloopVTable)->callback(this, dataLength, data, bufferLength, buffer);
39203924
return ret;
39213925
}
3926+
3927+
template <typename StatusType> void dummy1(StatusType* status)
3928+
{
3929+
if (cloopVTable->version < 3)
3930+
{
3931+
StatusType::setVersionError(status, "ICryptKeyCallback", cloopVTable->version, 3);
3932+
StatusType::checkException(status);
3933+
return;
3934+
}
3935+
StatusType::clearException(status);
3936+
static_cast<VTable*>(this->cloopVTable)->dummy1(this, status);
3937+
StatusType::checkException(status);
3938+
}
3939+
3940+
void dummy2()
3941+
{
3942+
if (cloopVTable->version < 3)
3943+
{
3944+
return;
3945+
}
3946+
static_cast<VTable*>(this->cloopVTable)->dummy2(this);
3947+
}
3948+
3949+
template <typename StatusType> int getHashLength(StatusType* status)
3950+
{
3951+
if (cloopVTable->version < 3)
3952+
{
3953+
StatusType::setVersionError(status, "ICryptKeyCallback", cloopVTable->version, 3);
3954+
StatusType::checkException(status);
3955+
return -1;
3956+
}
3957+
StatusType::clearException(status);
3958+
int ret = static_cast<VTable*>(this->cloopVTable)->getHashLength(this, status);
3959+
StatusType::checkException(status);
3960+
return ret;
3961+
}
3962+
3963+
template <typename StatusType> void getHashData(StatusType* status, void* hash)
3964+
{
3965+
if (cloopVTable->version < 3)
3966+
{
3967+
StatusType::setVersionError(status, "ICryptKeyCallback", cloopVTable->version, 3);
3968+
StatusType::checkException(status);
3969+
return;
3970+
}
3971+
StatusType::clearException(status);
3972+
static_cast<VTable*>(this->cloopVTable)->getHashData(this, status, hash);
3973+
StatusType::checkException(status);
3974+
}
39223975
};
39233976

39243977
#define FIREBIRD_IKEY_HOLDER_PLUGIN_VERSION 5u
@@ -14395,6 +14448,10 @@ namespace Firebird
1439514448
{
1439614449
this->version = Base::VERSION;
1439714450
this->callback = &Name::cloopcallbackDispatcher;
14451+
this->dummy1 = &Name::cloopdummy1Dispatcher;
14452+
this->dummy2 = &Name::cloopdummy2Dispatcher;
14453+
this->getHashLength = &Name::cloopgetHashLengthDispatcher;
14454+
this->getHashData = &Name::cloopgetHashDataDispatcher;
1439814455
}
1439914456
} vTable;
1440014457

@@ -14413,6 +14470,61 @@ namespace Firebird
1441314470
return static_cast<unsigned>(0);
1441414471
}
1441514472
}
14473+
14474+
static void CLOOP_CARG cloopdummy1Dispatcher(ICryptKeyCallback* self, IStatus* status) CLOOP_NOEXCEPT
14475+
{
14476+
StatusType status2(status);
14477+
14478+
try
14479+
{
14480+
static_cast<Name*>(self)->Name::dummy1(&status2);
14481+
}
14482+
catch (...)
14483+
{
14484+
StatusType::catchException(&status2);
14485+
}
14486+
}
14487+
14488+
static void CLOOP_CARG cloopdummy2Dispatcher(ICryptKeyCallback* self) CLOOP_NOEXCEPT
14489+
{
14490+
try
14491+
{
14492+
static_cast<Name*>(self)->Name::dummy2();
14493+
}
14494+
catch (...)
14495+
{
14496+
StatusType::catchException(0);
14497+
}
14498+
}
14499+
14500+
static int CLOOP_CARG cloopgetHashLengthDispatcher(ICryptKeyCallback* self, IStatus* status) CLOOP_NOEXCEPT
14501+
{
14502+
StatusType status2(status);
14503+
14504+
try
14505+
{
14506+
return static_cast<Name*>(self)->Name::getHashLength(&status2);
14507+
}
14508+
catch (...)
14509+
{
14510+
StatusType::catchException(&status2);
14511+
return static_cast<int>(0);
14512+
}
14513+
}
14514+
14515+
static void CLOOP_CARG cloopgetHashDataDispatcher(ICryptKeyCallback* self, IStatus* status, void* hash) CLOOP_NOEXCEPT
14516+
{
14517+
StatusType status2(status);
14518+
14519+
try
14520+
{
14521+
static_cast<Name*>(self)->Name::getHashData(&status2, hash);
14522+
}
14523+
catch (...)
14524+
{
14525+
StatusType::catchException(&status2);
14526+
}
14527+
}
1441614528
};
1441714529

1441814530
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<ICryptKeyCallback> > >
@@ -14429,6 +14541,14 @@ namespace Firebird
1442914541
}
1443014542

1443114543
virtual unsigned callback(unsigned dataLength, const void* data, unsigned bufferLength, void* buffer) = 0;
14544+
virtual void dummy1(StatusType* status)
14545+
{
14546+
}
14547+
virtual void dummy2()
14548+
{
14549+
}
14550+
virtual int getHashLength(StatusType* status) = 0;
14551+
virtual void getHashData(StatusType* status, void* hash) = 0;
1443214552
};
1443314553

1443414554
template <typename Name, typename StatusType, typename Base>

0 commit comments

Comments
 (0)