Looking at our new SQLite database code, I noticed that there is a potential problem in the method IsSQLiteFile(): If there is no terminating zero within the first 16 bytes of the file, the magic buffer would be over-read in the std::string constructor for magic_str. Fixed by using the "from buffer" variant of the string ctor (that also takes a size) rather than the "from c-string" variant (see http://www.cplusplus.com/reference/string/string/string/).
The behaviour can be reproduced by the following steps:
- Creating a file of at least 512 bytes in size (to pass the minimum size check) that doesn't contain zero bytes in the magic area, e.g. simply:
$ python3 -c "print('A'*512)" > /tmp/corrupt_wallet - Showing content and size of the
magic_strstring in case the magic check fails - Create a simple unit test that simply calls
IsSQLiteFilewith the corrupt wallet file - Run the unit test and see the random gibberish output of
magic_strafter 16As :-)
Or, TLDR variant, just get the branch https://github.com/theStack/bitcoin/tree/reproduce_sqlite_magic_overread, compile unit Tests and run the script ./reproduce_sqlite_magic_overread.sh.
Note that this is the minimal diff, probably it would be better to avoid std::string at all in this case and just use memcmp, strings that include null bytes are pretty confusing.