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 <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/check.h>
10 : : #include <util/fs.h>
11 : : #include <util/time.h>
12 : : #include <util/translation.h>
13 : : #include <wallet/db.h>
14 : : #include <wallet/dump.h>
15 : : #include <wallet/migrate.h>
16 : :
17 : : #include <fstream>
18 : : #include <iostream>
19 : :
20 : : using wallet::DatabaseOptions;
21 : : using wallet::DatabaseStatus;
22 : :
23 : : namespace {
24 : : TestingSetup* g_setup;
25 : : } // namespace
26 : :
27 : 1 : void initialize_wallet_bdb_parser()
28 : : {
29 [ + - + - : 1 : static auto testing_setup = MakeNoLogFileContext<TestingSetup>();
+ - ]
30 : 1 : g_setup = testing_setup.get();
31 : 1 : }
32 : :
33 [ + - ]: 578 : FUZZ_TARGET(wallet_bdb_parser, .init = initialize_wallet_bdb_parser)
34 : : {
35 [ + - ]: 204 : const auto wallet_path = g_setup->m_args.GetDataDirNet() / "fuzzed_wallet.dat";
36 : :
37 : 102 : {
38 [ + - + - ]: 204 : AutoFile outfile{fsbridge::fopen(wallet_path, "wb")};
39 [ + - ]: 102 : outfile << std::span{buffer};
40 [ + - - + ]: 204 : assert(outfile.fclose() == 0);
41 : 102 : }
42 : :
43 [ + - ]: 102 : const DatabaseOptions options{};
44 : 102 : DatabaseStatus status;
45 [ + - ]: 102 : bilingual_str error;
46 : :
47 [ + - ]: 204 : fs::path bdb_ro_dumpfile{g_setup->m_args.GetDataDirNet() / "fuzzed_dumpfile_bdb_ro.dump"};
48 [ + - + + ]: 102 : if (fs::exists(bdb_ro_dumpfile)) { // Writing into an existing dump file will throw an exception
49 [ + - ]: 5 : remove(bdb_ro_dumpfile);
50 : : }
51 [ - + + - : 306 : g_setup->m_args.ForceSetArg("-dumpfile", fs::PathToString(bdb_ro_dumpfile));
+ - ]
52 : :
53 [ + - ]: 102 : auto db{MakeBerkeleyRODatabase(wallet_path, options, status, error)};
54 [ + + ]: 102 : if (db) {
55 [ + - - + ]: 5 : assert(DumpWallet(g_setup->m_args, *db, error));
56 : : } else {
57 [ - + ]: 97 : if (error.original.starts_with("AutoFile::ignore: end of file") ||
58 [ + + ]: 96 : error.original.starts_with("AutoFile::read: end of file") ||
59 [ + - ]: 78 : error.original.starts_with("AutoFile::seek: ") ||
60 [ + + ]: 78 : error.original == "Not a BDB file" ||
61 [ + + ]: 76 : error.original == "Unexpected page type, should be 9 (BTree Metadata)" ||
62 [ + + ]: 74 : error.original == "Unexpected database flags, should only be 0x20 (subdatabases)" ||
63 [ + + ]: 72 : error.original == "Unexpected outer database root page type" ||
64 [ + + ]: 71 : error.original == "Unexpected number of entries in outer database root page" ||
65 [ + + ]: 69 : error.original == "Subdatabase page number has unexpected length" ||
66 [ + + ]: 67 : error.original == "Unknown record type in records page" ||
67 [ + - ]: 66 : error.original == "Unknown record type in internal page" ||
68 [ + - ]: 66 : error.original == "Unexpected page size" ||
69 [ + - ]: 66 : error.original == "Unexpected page type" ||
70 [ + + ]: 66 : error.original == "Page number mismatch" ||
71 [ + + ]: 64 : error.original == "Bad btree level" ||
72 [ + + ]: 60 : error.original == "Bad page size" ||
73 [ + + ]: 54 : error.original == "Meta page number mismatch" ||
74 [ + + ]: 53 : error.original == "Data record position not in page" ||
75 [ + - ]: 52 : error.original == "Internal record position not in page" ||
76 [ + + ]: 52 : 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" ||
77 [ + - ]: 19 : error.original == "Records page has odd number of records" ||
78 [ + - ]: 19 : error.original == "Bad overflow record page type" ||
79 [ + - ]: 19 : error.original == "BTree page has an unexpected level" ||
80 [ + + ]: 19 : error.original == "BTree Leaf page is not at level 1" ||
81 [ + - ]: 18 : error.original == "Subdatabase last page is greater than database last page" ||
82 [ + + ]: 18 : error.original == "Page number is greater than database last page" ||
83 [ + + ]: 17 : error.original == "Last page number could not fit in file" ||
84 [ + + ]: 15 : error.original == "Subdatabase has an unexpected name" ||
85 [ + + + + ]: 101 : error.original == "Unsupported BDB data file version number" ||
86 [ - + ]: 2 : error.original == "BDB builtin encryption is not supported") {
87 : : } else {
88 [ # # ]: 0 : throw std::runtime_error(error.original);
89 : : }
90 : : }
91 : 408 : }
|