@@ -166,10 +166,27 @@ class BerkeleyDatabase
166
166
bool IsDummy () { return env == nullptr ; }
167
167
};
168
168
169
-
170
169
/* * RAII class that provides access to a Berkeley database */
171
170
class BerkeleyBatch
172
171
{
172
+ /* * RAII class that automatically cleanses its data on destruction */
173
+ class SafeDbt final {
174
+ Dbt m_dbt;
175
+
176
+ public:
177
+ // construct Dbt with data or flags
178
+ SafeDbt (u_int32_t flags = 0 );
179
+ SafeDbt (void *data, size_t size);
180
+ ~SafeDbt ();
181
+
182
+ // delegate to Dbt
183
+ const void * get_data () const ;
184
+ u_int32_t get_size () const ;
185
+
186
+ // conversion operator to access the underlying Dbt
187
+ operator Dbt*();
188
+ };
189
+
173
190
protected:
174
191
Db* pdb;
175
192
std::string strFile;
@@ -197,7 +214,6 @@ class BerkeleyBatch
197
214
/* verifies the database file */
198
215
static bool VerifyDatabaseFile (const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
199
216
200
- public:
201
217
template <typename K, typename T>
202
218
bool Read (const K& key, T& value)
203
219
{
@@ -208,13 +224,11 @@ class BerkeleyBatch
208
224
CDataStream ssKey (SER_DISK, CLIENT_VERSION);
209
225
ssKey.reserve (1000 );
210
226
ssKey << key;
211
- Dbt datKey (ssKey.data (), ssKey.size ());
227
+ SafeDbt datKey (ssKey.data (), ssKey.size ());
212
228
213
229
// Read
214
- Dbt datValue;
215
- datValue.set_flags (DB_DBT_MALLOC);
216
- int ret = pdb->get (activeTxn, &datKey, &datValue, 0 );
217
- memory_cleanse (datKey.get_data (), datKey.get_size ());
230
+ SafeDbt datValue (DB_DBT_MALLOC);
231
+ int ret = pdb->get (activeTxn, datKey, datValue, 0 );
218
232
bool success = false ;
219
233
if (datValue.get_data () != nullptr ) {
220
234
// Unserialize value
@@ -225,10 +239,6 @@ class BerkeleyBatch
225
239
} catch (const std::exception&) {
226
240
// In this case success remains 'false'
227
241
}
228
-
229
- // Clear and free memory
230
- memory_cleanse (datValue.get_data (), datValue.get_size ());
231
- free (datValue.get_data ());
232
242
}
233
243
return ret == 0 && success;
234
244
}
@@ -245,20 +255,16 @@ class BerkeleyBatch
245
255
CDataStream ssKey (SER_DISK, CLIENT_VERSION);
246
256
ssKey.reserve (1000 );
247
257
ssKey << key;
248
- Dbt datKey (ssKey.data (), ssKey.size ());
258
+ SafeDbt datKey (ssKey.data (), ssKey.size ());
249
259
250
260
// Value
251
261
CDataStream ssValue (SER_DISK, CLIENT_VERSION);
252
262
ssValue.reserve (10000 );
253
263
ssValue << value;
254
- Dbt datValue (ssValue.data (), ssValue.size ());
264
+ SafeDbt datValue (ssValue.data (), ssValue.size ());
255
265
256
266
// Write
257
- int ret = pdb->put (activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
258
-
259
- // Clear memory in case it was a private key
260
- memory_cleanse (datKey.get_data (), datKey.get_size ());
261
- memory_cleanse (datValue.get_data (), datValue.get_size ());
267
+ int ret = pdb->put (activeTxn, datKey, datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
262
268
return (ret == 0 );
263
269
}
264
270
@@ -274,13 +280,10 @@ class BerkeleyBatch
274
280
CDataStream ssKey (SER_DISK, CLIENT_VERSION);
275
281
ssKey.reserve (1000 );
276
282
ssKey << key;
277
- Dbt datKey (ssKey.data (), ssKey.size ());
283
+ SafeDbt datKey (ssKey.data (), ssKey.size ());
278
284
279
285
// Erase
280
- int ret = pdb->del (activeTxn, &datKey, 0 );
281
-
282
- // Clear memory
283
- memory_cleanse (datKey.get_data (), datKey.get_size ());
286
+ int ret = pdb->del (activeTxn, datKey, 0 );
284
287
return (ret == 0 || ret == DB_NOTFOUND);
285
288
}
286
289
@@ -294,13 +297,10 @@ class BerkeleyBatch
294
297
CDataStream ssKey (SER_DISK, CLIENT_VERSION);
295
298
ssKey.reserve (1000 );
296
299
ssKey << key;
297
- Dbt datKey (ssKey.data (), ssKey.size ());
300
+ SafeDbt datKey (ssKey.data (), ssKey.size ());
298
301
299
302
// Exists
300
- int ret = pdb->exists (activeTxn, &datKey, 0 );
301
-
302
- // Clear memory
303
- memory_cleanse (datKey.get_data (), datKey.get_size ());
303
+ int ret = pdb->exists (activeTxn, datKey, 0 );
304
304
return (ret == 0 );
305
305
}
306
306
@@ -318,11 +318,9 @@ class BerkeleyBatch
318
318
int ReadAtCursor (Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue)
319
319
{
320
320
// Read at cursor
321
- Dbt datKey;
322
- Dbt datValue;
323
- datKey.set_flags (DB_DBT_MALLOC);
324
- datValue.set_flags (DB_DBT_MALLOC);
325
- int ret = pcursor->get (&datKey, &datValue, DB_NEXT);
321
+ SafeDbt datKey (DB_DBT_MALLOC);
322
+ SafeDbt datValue (DB_DBT_MALLOC);
323
+ int ret = pcursor->get (datKey, datValue, DB_NEXT);
326
324
if (ret != 0 )
327
325
return ret;
328
326
else if (datKey.get_data () == nullptr || datValue.get_data () == nullptr )
@@ -335,16 +333,9 @@ class BerkeleyBatch
335
333
ssValue.SetType (SER_DISK);
336
334
ssValue.clear ();
337
335
ssValue.write ((char *)datValue.get_data (), datValue.get_size ());
338
-
339
- // Clear and free memory
340
- memory_cleanse (datKey.get_data (), datKey.get_size ());
341
- memory_cleanse (datValue.get_data (), datValue.get_size ());
342
- free (datKey.get_data ());
343
- free (datValue.get_data ());
344
336
return 0 ;
345
337
}
346
338
347
- public:
348
339
bool TxnBegin ()
349
340
{
350
341
if (!pdb || activeTxn)
0 commit comments