LCOV - code coverage report
Current view: top level - src/wallet/test/fuzz - wallet_bdb_parser.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 0.0 % 73 0
Test Date: 2024-08-28 04:44:32 Functions: 0.0 % 3 0
Branches: 0.0 % 150 0

             Branch data     Line data    Source code
       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 <config/bitcoin-config.h> // IWYU pragma: keep
       6                 :             : #include <test/fuzz/FuzzedDataProvider.h>
       7                 :             : #include <test/fuzz/fuzz.h>
       8                 :             : #include <test/fuzz/util.h>
       9                 :             : #include <test/util/setup_common.h>
      10                 :             : #include <util/fs.h>
      11                 :             : #include <util/time.h>
      12                 :             : #include <util/translation.h>
      13                 :             : #include <wallet/bdb.h>
      14                 :             : #include <wallet/db.h>
      15                 :             : #include <wallet/dump.h>
      16                 :             : #include <wallet/migrate.h>
      17                 :             : 
      18                 :             : #include <fstream>
      19                 :             : #include <iostream>
      20                 :             : 
      21                 :             : using wallet::DatabaseOptions;
      22                 :             : using wallet::DatabaseStatus;
      23                 :             : 
      24                 :             : namespace {
      25                 :             : TestingSetup* g_setup;
      26                 :             : } // namespace
      27                 :             : 
      28                 :           0 : void initialize_wallet_bdb_parser()
      29                 :             : {
      30   [ #  #  #  # ]:           0 :     static auto testing_setup = MakeNoLogFileContext<TestingSetup>();
      31                 :           0 :     g_setup = testing_setup.get();
      32         [ #  # ]:           0 : }
      33                 :             : 
      34         [ #  # ]:           0 : FUZZ_TARGET(wallet_bdb_parser, .init = initialize_wallet_bdb_parser)
      35                 :             : {
      36         [ #  # ]:           0 :     const auto wallet_path = g_setup->m_args.GetDataDirNet() / "fuzzed_wallet.dat";
      37                 :             : 
      38                 :           0 :     {
      39         [ #  # ]:           0 :         AutoFile outfile{fsbridge::fopen(wallet_path, "wb")};
      40         [ #  # ]:           0 :         outfile << Span{buffer};
      41                 :           0 :     }
      42                 :             : 
      43         [ #  # ]:           0 :     const DatabaseOptions options{};
      44                 :           0 :     DatabaseStatus status;
      45         [ #  # ]:           0 :     bilingual_str error;
      46                 :             : 
      47   [ #  #  #  # ]:           0 :     fs::path bdb_ro_dumpfile{g_setup->m_args.GetDataDirNet() / "fuzzed_dumpfile_bdb_ro.dump"};
      48   [ #  #  #  # ]:           0 :     if (fs::exists(bdb_ro_dumpfile)) { // Writing into an existing dump file will throw an exception
      49         [ #  # ]:           0 :         remove(bdb_ro_dumpfile);
      50                 :             :     }
      51   [ #  #  #  #  :           0 :     g_setup->m_args.ForceSetArg("-dumpfile", fs::PathToString(bdb_ro_dumpfile));
                   #  # ]
      52                 :             : 
      53                 :             : #ifdef USE_BDB
      54                 :           0 :     bool bdb_ro_err = false;
      55                 :           0 :     bool bdb_ro_strict_err = false;
      56                 :             : #endif
      57         [ #  # ]:           0 :     auto db{MakeBerkeleyRODatabase(wallet_path, options, status, error)};
      58         [ #  # ]:           0 :     if (db) {
      59   [ #  #  #  # ]:           0 :         assert(DumpWallet(g_setup->m_args, *db, error));
      60                 :             :     } else {
      61                 :             : #ifdef USE_BDB
      62                 :           0 :         bdb_ro_err = true;
      63                 :             : #endif
      64                 :           0 :         if (error.original.starts_with("AutoFile::ignore: end of file") ||
      65         [ #  # ]:           0 :             error.original.starts_with("AutoFile::read: end of file") ||
      66         [ #  # ]:           0 :             error.original.starts_with("AutoFile::seek: ") ||
      67         [ #  # ]:           0 :             error.original == "Not a BDB file" ||
      68         [ #  # ]:           0 :             error.original == "Unexpected page type, should be 9 (BTree Metadata)" ||
      69         [ #  # ]:           0 :             error.original == "Unexpected database flags, should only be 0x20 (subdatabases)" ||
      70         [ #  # ]:           0 :             error.original == "Unexpected outer database root page type" ||
      71         [ #  # ]:           0 :             error.original == "Unexpected number of entries in outer database root page" ||
      72         [ #  # ]:           0 :             error.original == "Subdatabase page number has unexpected length" ||
      73         [ #  # ]:           0 :             error.original == "Unknown record type in records page" ||
      74         [ #  # ]:           0 :             error.original == "Unknown record type in internal page" ||
      75         [ #  # ]:           0 :             error.original == "Unexpected page size" ||
      76         [ #  # ]:           0 :             error.original == "Unexpected page type" ||
      77         [ #  # ]:           0 :             error.original == "Page number mismatch" ||
      78         [ #  # ]:           0 :             error.original == "Bad btree level" ||
      79         [ #  # ]:           0 :             error.original == "Bad page size" ||
      80         [ #  # ]:           0 :             error.original == "Meta page number mismatch" ||
      81         [ #  # ]:           0 :             error.original == "Data record position not in page" ||
      82         [ #  # ]:           0 :             error.original == "Internal record position not in page" ||
      83         [ #  # ]:           0 :             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" ||
      84   [ #  #  #  # ]:           0 :             error.original == "Records page has odd number of records" ||
      85         [ #  # ]:           0 :             error.original == "Bad overflow record page type") {
      86                 :             :             // Do nothing
      87                 :           0 :         } else if (error.original == "Subdatabase last page is greater than database last page" ||
      88         [ #  # ]:           0 :                    error.original == "Page number is greater than database last page" ||
      89         [ #  # ]:           0 :                    error.original == "Last page number could not fit in file" ||
      90         [ #  # ]:           0 :                    error.original == "Subdatabase has an unexpected name" ||
      91   [ #  #  #  # ]:           0 :                    error.original == "Unsupported BDB data file version number" ||
      92         [ #  # ]:           0 :                    error.original == "BDB builtin encryption is not supported") {
      93                 :             : #ifdef USE_BDB
      94                 :             :             bdb_ro_strict_err = true;
      95                 :             : #endif
      96                 :             :         } else {
      97         [ #  # ]:           0 :             throw std::runtime_error(error.original);
      98                 :             :         }
      99                 :             :     }
     100                 :             : 
     101                 :             : #ifdef USE_BDB
     102                 :             :     // Try opening with BDB
     103   [ #  #  #  # ]:           0 :     fs::path bdb_dumpfile{g_setup->m_args.GetDataDirNet() / "fuzzed_dumpfile_bdb.dump"};
     104   [ #  #  #  # ]:           0 :     if (fs::exists(bdb_dumpfile)) { // Writing into an existing dump file will throw an exception
     105         [ #  # ]:           0 :         remove(bdb_dumpfile);
     106                 :             :     }
     107   [ #  #  #  #  :           0 :     g_setup->m_args.ForceSetArg("-dumpfile", fs::PathToString(bdb_dumpfile));
                   #  # ]
     108                 :             : 
     109                 :           0 :     try {
     110         [ #  # ]:           0 :         auto db{MakeBerkeleyDatabase(wallet_path, options, status, error)};
     111   [ #  #  #  # ]:           0 :         if (bdb_ro_err && !db) {
     112                 :             :             return;
     113                 :             :         }
     114         [ #  # ]:           0 :         assert(db);
     115         [ #  # ]:           0 :         if (bdb_ro_strict_err) {
     116                 :             :             // BerkeleyRO will be stricter than BDB. Ignore when those specific errors are hit.
     117                 :             :             return;
     118                 :             :         }
     119         [ #  # ]:           0 :         assert(!bdb_ro_err);
     120   [ #  #  #  # ]:           0 :         assert(DumpWallet(g_setup->m_args, *db, error));
     121         [ #  # ]:           0 :     } catch (const std::runtime_error& e) {
     122         [ -  - ]:           0 :         if (bdb_ro_err) return;
     123                 :           0 :         throw e;
     124                 :           0 :     }
     125                 :             : 
     126                 :             :     // Make sure the dumpfiles match
     127   [ #  #  #  #  :           0 :     if (fs::exists(bdb_ro_dumpfile) && fs::exists(bdb_dumpfile)) {
                   #  # ]
     128         [ #  # ]:           0 :         std::ifstream bdb_ro_dump(bdb_ro_dumpfile, std::ios_base::binary | std::ios_base::in);
     129         [ #  # ]:           0 :         std::ifstream bdb_dump(bdb_dumpfile, std::ios_base::binary | std::ios_base::in);
     130   [ #  #  #  # ]:           0 :         assert(std::equal(
     131                 :             :             std::istreambuf_iterator<char>(bdb_ro_dump.rdbuf()),
     132                 :             :             std::istreambuf_iterator<char>(),
     133                 :             :             std::istreambuf_iterator<char>(bdb_dump.rdbuf())));
     134                 :           0 :     }
     135                 :             : #endif
     136                 :           0 : }
        

Generated by: LCOV version 2.0-1