wallet_bdb_parser.cpp raw

   1  // Copyright (c) 2023-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #include <test/fuzz/FuzzedDataProvider.h>
   6  #include <test/fuzz/fuzz.h>
   7  #include <test/fuzz/util.h>
   8  #include <test/util/setup_common.h>
   9  #include <util/fs.h>
  10  #include <util/time.h>
  11  #include <util/translation.h>
  12  #include <wallet/db.h>
  13  #include <wallet/dump.h>
  14  #include <wallet/migrate.h>
  15  
  16  #include <fstream>
  17  #include <iostream>
  18  
  19  using wallet::DatabaseOptions;
  20  using wallet::DatabaseStatus;
  21  
  22  namespace {
  23  TestingSetup* g_setup;
  24  } // namespace
  25  
  26  void initialize_wallet_bdb_parser()
  27  {
  28      static auto testing_setup = MakeNoLogFileContext<TestingSetup>();
  29      g_setup = testing_setup.get();
  30  }
  31  
  32  FUZZ_TARGET(wallet_bdb_parser, .init = initialize_wallet_bdb_parser)
  33  {
  34      const auto wallet_path = g_setup->m_args.GetDataDirNet() / "fuzzed_wallet.dat";
  35  
  36      {
  37          AutoFile outfile{fsbridge::fopen(wallet_path, "wb")};
  38          outfile << std::span{buffer};
  39          assert(outfile.fclose() == 0);
  40      }
  41  
  42      const DatabaseOptions options{};
  43      DatabaseStatus status;
  44      bilingual_str error;
  45  
  46      fs::path bdb_ro_dumpfile{g_setup->m_args.GetDataDirNet() / "fuzzed_dumpfile_bdb_ro.dump"};
  47      if (fs::exists(bdb_ro_dumpfile)) { // Writing into an existing dump file will throw an exception
  48          remove(bdb_ro_dumpfile);
  49      }
  50      g_setup->m_args.ForceSetArg("-dumpfile", fs::PathToString(bdb_ro_dumpfile));
  51  
  52      auto db{MakeBerkeleyRODatabase(wallet_path, options, status, error)};
  53      if (db) {
  54          assert(DumpWallet(g_setup->m_args, *db, error));
  55      } else {
  56          if (error.original.starts_with("AutoFile::ignore: end of file") ||
  57              error.original.starts_with("AutoFile::read: end of file") ||
  58              error.original.starts_with("AutoFile::seek: ") ||
  59              error.original == "Not a BDB file" ||
  60              error.original == "Unexpected page type, should be 9 (BTree Metadata)" ||
  61              error.original == "Unexpected database flags, should only be 0x20 (subdatabases)" ||
  62              error.original == "Unexpected outer database root page type" ||
  63              error.original == "Unexpected number of entries in outer database root page" ||
  64              error.original == "Subdatabase page number has unexpected length" ||
  65              error.original == "Unknown record type in records page" ||
  66              error.original == "Unknown record type in internal page" ||
  67              error.original == "Unexpected page size" ||
  68              error.original == "Unexpected page type" ||
  69              error.original == "Page number mismatch" ||
  70              error.original == "Bad btree level" ||
  71              error.original == "Bad page size" ||
  72              error.original == "Meta page number mismatch" ||
  73              error.original == "Data record position not in page" ||
  74              error.original == "Internal record position not in page" ||
  75              error.original == "LSNs are not reset, this database is not completely flushed. Please reopen then close the database with a version that has BDB support" ||
  76              error.original == "Records page has odd number of records" ||
  77              error.original == "Bad overflow record page type" ||
  78              error.original == "BTree page has an unexpected level" ||
  79              error.original == "BTree Leaf page is not at level 1" ||
  80              error.original == "Subdatabase last page is greater than database last page" ||
  81              error.original == "Page number is greater than database last page" ||
  82              error.original == "Last page number could not fit in file" ||
  83              error.original == "Subdatabase has an unexpected name" ||
  84              error.original == "Unsupported BDB data file version number" ||
  85              error.original == "BDB builtin encryption is not supported") {
  86          } else {
  87              throw std::runtime_error(error.original);
  88          }
  89      }
  90  }
  91