wallet_bdb_parser.cpp
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 // Do nothing 79 } else if (error.original == "Subdatabase last page is greater than database last page" || 80 error.original == "Page number is greater than database last page" || 81 error.original == "Last page number could not fit in file" || 82 error.original == "Subdatabase has an unexpected name" || 83 error.original == "Unsupported BDB data file version number" || 84 error.original == "BDB builtin encryption is not supported") { 85 } else { 86 throw std::runtime_error(error.original); 87 } 88 } 89 }