The read-only BDB parser (BerkeleyRODatabase::Open() in migrate.cpp) is fed an
attacker-supplied file whenever a user runs migratewallet, loads a legacy
.dat wallet, or runs bitcoin-wallet. #34959 hardened it against circular
references, but three crafted-file cases still get through and turn a small file
into unbounded CPU or memory.
Revisited btree page. The level check rejects a page that is its own ancestor, but a page reachable from more than one parent stays level consistent, passes the check, and is parsed once per path to it. An ~8 KB file of shared subtrees does not finish.
Overflow chain of empty pages. #34959 bounds an overflow chain by the stated data length, but pages that carry no data never advance it, so two empty overflow pages pointing at each other loop forever.
Page records that do not fit. A page's index entries can all point at the
same record, which is then read and kept once per entry. entries and the
record length are both 16-bit, so a single ~64 KB page can be read into
entries * len bytes. A 256 KB file takes a node from 54 MB to ~800 MB during
migratewallet, and distinct such pages add up to an OOM.
None of these corrupt memory; they are CPU/memory exhaustion from a crafted or corrupted wallet file, the same threat model #34959 addressed.
The first two are fixed by tracking visited pages in each traversal (the approach from #34946 / #35150, closed as superseded by #34959, which turns out not to cover these level-consistent and empty-page cases). The third is fixed by bounding a page's total record size to the page. A valid BDB database references each page once and its records fit within the page, so none of this rejects a file that parses today.
Each fix is a separate commit with a regression test in db_tests.cpp that
hand-crafts the relevant file (Core cannot write a BDB database, so the bytes are
laid out directly) and checks the parser rejects it. The three new error strings
are also added to the wallet_bdb_parser fuzz allow-list.
Supersedes #35992, which proposed the record-size bound on its own.