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