Skip to content

Commit e411b70

Browse files
promagrandom-zebra
authored andcommitted
[wallet] Fix leak in CDB constructor
Now using a std::unique_ptr, the Db instance is correctly released when CDB initialization fails. The internal CDB state and mapFileUseCount are only mutated when the CDB initialization succeeds.
1 parent f15aeea commit e411b70

File tree

1 file changed

+22
-25
lines changed

1 file changed

+22
-25
lines changed

src/wallet/db.cpp

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,8 @@ void CDBEnv::CheckpointLSN(const std::string& strFile)
352352
}
353353

354354

355-
CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL)
355+
CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb(nullptr), activeTxn(nullptr)
356356
{
357-
int ret;
358357
fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
359358
fFlushOnClose = fFlushOnCloseIn;
360359
env = dbw.env;
@@ -363,7 +362,7 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb
363362
}
364363
const std::string &strFilename = dbw.strFile;
365364

366-
bool fCreate = strchr(pszMode, 'c') != NULL;
365+
bool fCreate = strchr(pszMode, 'c') != nullptr;
367366
unsigned int nFlags = DB_THREAD;
368367
if (fCreate)
369368
nFlags |= DB_CREATE;
@@ -373,45 +372,43 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb
373372
if (!env->Open(GetDataDir()))
374373
throw std::runtime_error("CDB: Failed to open database environment.");
375374

376-
strFile = strFilename;
377-
++env->mapFileUseCount[strFile];
378-
pdb = env->mapDb[strFile];
379-
if (pdb == NULL) {
380-
pdb = new Db(env->dbenv, 0);
375+
pdb = env->mapDb[strFilename];
376+
if (pdb == nullptr) {
377+
int ret;
378+
std::unique_ptr<Db> pdb_temp(new Db(env->dbenv, 0));
381379

382380
bool fMockDb = env->IsMock();
383381
if (fMockDb) {
384-
DbMpoolFile* mpf = pdb->get_mpf();
382+
DbMpoolFile* mpf = pdb_temp->get_mpf();
385383
ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
386-
if (ret != 0)
387-
throw std::runtime_error(strprintf("CDB : Failed to configure for no temp file backing for database %s", strFile));
384+
if (ret != 0) {
385+
throw std::runtime_error(strprintf("CDB: Failed to configure for no temp file backing for database %s", strFilename));
386+
}
388387
}
389388

390-
ret = pdb->open(NULL, // Txn pointer
391-
fMockDb ? NULL : strFile.c_str(), // Filename
392-
fMockDb ? strFile.c_str() : "main", // Logical db name
393-
DB_BTREE, // Database type
394-
nFlags, // Flags
395-
0);
389+
ret = pdb_temp->open(nullptr, // Txn pointer
390+
fMockDb ? nullptr : strFilename.c_str(), // Filename
391+
fMockDb ? strFilename.c_str() : "main", // Logical db name
392+
DB_BTREE, // Database type
393+
nFlags, // Flags
394+
0);
396395

397396
if (ret != 0) {
398-
delete pdb;
399-
pdb = NULL;
400-
--env->mapFileUseCount[strFile];
401-
std::string tempCopy(strFile);
402-
strFile = "";
403-
throw std::runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, tempCopy));
397+
throw std::runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFilename));
404398
}
405399

400+
pdb = pdb_temp.release();
401+
env->mapDb[strFilename] = pdb;
402+
406403
if (fCreate && !Exists(std::string("version"))) {
407404
bool fTmp = fReadOnly;
408405
fReadOnly = false;
409406
WriteVersion(CLIENT_VERSION);
410407
fReadOnly = fTmp;
411408
}
412-
413-
env->mapDb[strFile] = pdb;
414409
}
410+
++env->mapFileUseCount[strFilename];
411+
strFile = strFilename;
415412
}
416413
}
417414

0 commit comments

Comments
 (0)