upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main_gui.cpp
diff options
context:
space:
mode:
authorBitflash <btf01@proton.me>2026-07-29 17:41:10 -0300
committerGitHub <noreply@github.com>2026-07-29 17:41:10 -0300
commit72683da2b01286030fd61228168712c84aea79d4 (patch)
tree0b299e830282e483a1642e3b2ca38fb68507e646 /src/main_gui.cpp
parentc404e1c7f5d3f04d07e7e5b35a7a8ffcc998d855 (diff)
db: catch BDB exceptions so unreadable files fail cleanly (#34) (#38)
Berkeley DB throws when it cannot open a file written by another platform's build (e.g. BDB 5.3 wallet read by 6.2). Nothing on the call path caught these, so the exception unwound into std::terminate -- surfacing on Windows as STATUS_STACK_BUFFER_OVERRUN (0xC0000409) with no useful message. Three layers of defense: 1. main_gui.cpp: try/catch around LoadBlockIndex() and LoadWallet(), printing the reason and exiting cleanly. 2. db.cpp LoadWallet: try/catch around the record-reading loop (Satoshi's 2009 TODO), tracking the last record type so the error message says what it choked on. 3. db.cpp cleanup paths: every dbenv.close(), pdb->close(), txn_checkpoint() and log_archive() wrapped in try/catch so the environment teardown after a failed open does not throw a second exception into std::terminate. Tested: cross-platform wallet (Linux BDB 5.3 → Windows 6.2) now prints a clear message and exits with code 1, wallet left untouched. Closes #34 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src/main_gui.cpp')
-rw-r--r--src/main_gui.cpp41
1 files changed, 38 insertions, 3 deletions
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 99e63d4..a94d01d 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -170,11 +170,46 @@ int main(int argc, char* argv[])
170 170
171 ParseStartupArguments(argc, argv); 171 ParseStartupArguments(argc, argv);
172 172
173 printf("Loading block index...\n"); 173 // Berkeley DB reports failure by throwing, and CDB's constructor lets it
174 // through. Nothing on this path caught anything, so an unreadable
175 // blkindex.dat or wallet.dat -- one written by another platform's Berkeley
176 // DB, a truncated file, a version mismatch -- unwound out of main() into
177 // std::terminate and abort(). On Windows that surfaces as
178 // STATUS_STACK_BUFFER_OVERRUN (0xC0000409) inside ucrtbase.dll: no message,
179 // no log line past "Loading wallet...", and a faulting module with nothing
180 // to do with the real problem. Confirmed by stack trace:
181 //
182 // libdb_cxx-6.2.dll -> CDB::CDB(...) -> LoadBlockIndex(...) -> main()
183 //
184 // The program knew what had gone wrong and threw the reason away.
174 string strErrors; 185 string strErrors;
175 if (!LoadBlockIndex()) { fprintf(stderr,"LoadBlockIndex failed\n"); return 1; } 186 printf("Loading block index...\n");
187 try
188 {
189 if (!LoadBlockIndex()) { fprintf(stderr, "LoadBlockIndex failed\n"); return 1; }
190 }
191 catch (const std::exception& e)
192 {
193 fprintf(stderr, "Cannot read the block index: %s\n", e.what());
194 fprintf(stderr, "blkindex.dat and blk0001.dat may be from another machine or "
195 "incomplete. Deleting both is safe -- they are re-downloaded -- "
196 "but never delete wallet.dat, which holds your keys.\n");
197 return 1;
198 }
199
176 printf("Loading wallet...\n"); 200 printf("Loading wallet...\n");
177 if (!LoadWallet()) { fprintf(stderr,"LoadWallet failed\n"); return 1; } 201 try
202 {
203 if (!LoadWallet()) { fprintf(stderr, "LoadWallet failed\n"); return 1; }
204 }
205 catch (const std::exception& e)
206 {
207 fprintf(stderr, "Cannot read wallet.dat: %s\n", e.what());
208 fprintf(stderr, "The file was left untouched. A wallet.dat written by a "
209 "different platform's Berkeley DB is the usual cause; back it "
210 "up before trying anything else.\n");
211 return 1;
212 }
178 printf("Height=%d\n", nBestHeight); 213 printf("Height=%d\n", nBestHeight);
179 ReacceptWalletTransactions(); 214 ReacceptWalletTransactions();
180 215