@@ -191,10 +191,29 @@ class BerkeleyDatabase
191
191
bool IsDummy () { return env == nullptr ; }
192
192
};
193
193
194
-
195
194
/* * RAII class that provides access to a Berkeley database */
196
195
class BerkeleyBatch
197
196
{
197
+ /* * RAII class that automatically cleanses its data on destruction */
198
+ class SafeDbt final
199
+ {
200
+ Dbt m_dbt;
201
+
202
+ public:
203
+ // construct Dbt with internally-managed data
204
+ SafeDbt ();
205
+ // construct Dbt with provided data
206
+ SafeDbt (void * data, size_t size);
207
+ ~SafeDbt ();
208
+
209
+ // delegate to Dbt
210
+ const void * get_data () const ;
211
+ u_int32_t get_size () const ;
212
+
213
+ // conversion operator to access the underlying Dbt
214
+ operator Dbt*();
215
+ };
216
+
198
217
protected:
199
218
Db* pdb;
200
219
std::string strFile;
@@ -222,7 +241,6 @@ class BerkeleyBatch
222
241
/* verifies the database file */
223
242
static bool VerifyDatabaseFile (const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
224
243
225
- public:
226
244
template <typename K, typename T>
227
245
bool Read (const K& key, T& value)
228
246
{
@@ -233,13 +251,11 @@ class BerkeleyBatch
233
251
CDataStream ssKey (SER_DISK, CLIENT_VERSION);
234
252
ssKey.reserve (1000 );
235
253
ssKey << key;
236
- Dbt datKey (ssKey.data (), ssKey.size ());
254
+ SafeDbt datKey (ssKey.data (), ssKey.size ());
237
255
238
256
// Read
239
- Dbt datValue;
240
- datValue.set_flags (DB_DBT_MALLOC);
241
- int ret = pdb->get (activeTxn, &datKey, &datValue, 0 );
242
- memory_cleanse (datKey.get_data (), datKey.get_size ());
257
+ SafeDbt datValue;
258
+ int ret = pdb->get (activeTxn, datKey, datValue, 0 );
243
259
bool success = false ;
244
260
if (datValue.get_data () != nullptr ) {
245
261
// Unserialize value
@@ -250,10 +266,6 @@ class BerkeleyBatch
250
266
} catch (const std::exception&) {
251
267
// In this case success remains 'false'
252
268
}
253
-
254
- // Clear and free memory
255
- memory_cleanse (datValue.get_data (), datValue.get_size ());
256
- free (datValue.get_data ());
257
269
}
258
270
return ret == 0 && success;
259
271
}
@@ -270,20 +282,16 @@ class BerkeleyBatch
270
282
CDataStream ssKey (SER_DISK, CLIENT_VERSION);
271
283
ssKey.reserve (1000 );
272
284
ssKey << key;
273
- Dbt datKey (ssKey.data (), ssKey.size ());
285
+ SafeDbt datKey (ssKey.data (), ssKey.size ());
274
286
275
287
// Value
276
288
CDataStream ssValue (SER_DISK, CLIENT_VERSION);
277
289
ssValue.reserve (10000 );
278
290
ssValue << value;
279
- Dbt datValue (ssValue.data (), ssValue.size ());
291
+ SafeDbt datValue (ssValue.data (), ssValue.size ());
280
292
281
293
// Write
282
- int ret = pdb->put (activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
283
-
284
- // Clear memory in case it was a private key
285
- memory_cleanse (datKey.get_data (), datKey.get_size ());
286
- memory_cleanse (datValue.get_data (), datValue.get_size ());
294
+ int ret = pdb->put (activeTxn, datKey, datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
287
295
return (ret == 0 );
288
296
}
289
297
@@ -299,13 +307,10 @@ class BerkeleyBatch
299
307
CDataStream ssKey (SER_DISK, CLIENT_VERSION);
300
308
ssKey.reserve (1000 );
301
309
ssKey << key;
302
- Dbt datKey (ssKey.data (), ssKey.size ());
310
+ SafeDbt datKey (ssKey.data (), ssKey.size ());
303
311
304
312
// Erase
305
- int ret = pdb->del (activeTxn, &datKey, 0 );
306
-
307
- // Clear memory
308
- memory_cleanse (datKey.get_data (), datKey.get_size ());
313
+ int ret = pdb->del (activeTxn, datKey, 0 );
309
314
return (ret == 0 || ret == DB_NOTFOUND);
310
315
}
311
316
@@ -319,13 +324,10 @@ class BerkeleyBatch
319
324
CDataStream ssKey (SER_DISK, CLIENT_VERSION);
320
325
ssKey.reserve (1000 );
321
326
ssKey << key;
322
- Dbt datKey (ssKey.data (), ssKey.size ());
327
+ SafeDbt datKey (ssKey.data (), ssKey.size ());
323
328
324
329
// Exists
325
- int ret = pdb->exists (activeTxn, &datKey, 0 );
326
-
327
- // Clear memory
328
- memory_cleanse (datKey.get_data (), datKey.get_size ());
330
+ int ret = pdb->exists (activeTxn, datKey, 0 );
329
331
return (ret == 0 );
330
332
}
331
333
@@ -340,20 +342,12 @@ class BerkeleyBatch
340
342
return pcursor;
341
343
}
342
344
343
- int ReadAtCursor (Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, bool setRange = false )
345
+ int ReadAtCursor (Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue)
344
346
{
345
347
// Read at cursor
346
- Dbt datKey;
347
- unsigned int fFlags = DB_NEXT;
348
- if (setRange) {
349
- datKey.set_data (ssKey.data ());
350
- datKey.set_size (ssKey.size ());
351
- fFlags = DB_SET_RANGE;
352
- }
353
- Dbt datValue;
354
- datKey.set_flags (DB_DBT_MALLOC);
355
- datValue.set_flags (DB_DBT_MALLOC);
356
- int ret = pcursor->get (&datKey, &datValue, fFlags );
348
+ SafeDbt datKey;
349
+ SafeDbt datValue;
350
+ int ret = pcursor->get (datKey, datValue, DB_NEXT);
357
351
if (ret != 0 )
358
352
return ret;
359
353
else if (datKey.get_data () == nullptr || datValue.get_data () == nullptr )
@@ -366,16 +360,9 @@ class BerkeleyBatch
366
360
ssValue.SetType (SER_DISK);
367
361
ssValue.clear ();
368
362
ssValue.write ((char *)datValue.get_data (), datValue.get_size ());
369
-
370
- // Clear and free memory
371
- memory_cleanse (datKey.get_data (), datKey.get_size ());
372
- memory_cleanse (datValue.get_data (), datValue.get_size ());
373
- free (datKey.get_data ());
374
- free (datValue.get_data ());
375
363
return 0 ;
376
364
}
377
365
378
- public:
379
366
bool TxnBegin ()
380
367
{
381
368
if (!pdb || activeTxn)
0 commit comments