From f94b64c2f3a1994a21c4d99a1806d4f9611f810c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 22 May 2012 15:12:52 -0400 Subject: [PATCH 1/2] Prevent crashes due to missing or corrupted database records Any problems seen during deserialization will throw an uncaught exception, crashing the entire bitcoin process. Properly return an error instead, so that we may at least log the error and gracefully shutdown other portions of the app. --- src/db.cpp | 16 ++++++++++++++-- src/db.h | 9 +++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/db.cpp b/src/db.cpp index a0b9dc20..5c169fe0 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -416,9 +416,15 @@ bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector& string strType; uint160 hashItem; CDiskTxPos pos; - ssKey >> strType >> hashItem >> pos; int nItemHeight; - ssValue >> nItemHeight; + + try { + ssKey >> strType >> hashItem >> pos; + ssValue >> nItemHeight; + } + catch (std::exception &e) { + return error("%s() : deserialize error", __PRETTY_FUNCTION__); + } // Read transaction if (strType != "owner" || hashItem != hash160) @@ -533,6 +539,8 @@ bool CTxDB::LoadBlockIndex() return false; // Unserialize + + try { string strType; ssKey >> strType; if (strType == "blockindex" && !fRequestShutdown) @@ -564,6 +572,10 @@ bool CTxDB::LoadBlockIndex() { break; // if shutdown requested or finished loading block index } + } // try + catch (std::exception &e) { + return error("%s() : deserialize error", __PRETTY_FUNCTION__); + } } pcursor->close(); diff --git a/src/db.h b/src/db.h index b8fc4db5..a67193b6 100644 --- a/src/db.h +++ b/src/db.h @@ -72,8 +72,13 @@ protected: return false; // Unserialize value - CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION); - ssValue >> value; + try { + CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION); + ssValue >> value; + } + catch (std::exception &e) { + return false; + } // Clear and free memory memset(datValue.get_data(), 0, datValue.get_size()); From 8fe791e4e2db4b66f47d44d2ecaf734e2a36e5ed Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 22 May 2012 15:23:17 -0400 Subject: [PATCH 2/2] Prevent crashes due to missing or corrupted blk????.dat records In LoadExternalBlockFile(), errors are already caught... silently. Add a warning message, even though we do not abort the program due to load error. --- src/main.cpp | 5 +++-- src/main.h | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b925f8d5..388947e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2133,8 +2133,9 @@ bool LoadExternalBlockFile(FILE* fileIn) } } } - catch (std::exception &e) - { + catch (std::exception &e) { + printf("%s() : Deserialize or I/O error caught during load\n", + __PRETTY_FUNCTION__); } } printf("Loaded %i blocks from external file\n", nLoaded); diff --git a/src/main.h b/src/main.h index ac5ba254..c0fe63a3 100644 --- a/src/main.h +++ b/src/main.h @@ -593,7 +593,13 @@ public: // Read transaction if (fseek(filein, pos.nTxPos, SEEK_SET) != 0) return error("CTransaction::ReadFromDisk() : fseek failed"); - filein >> *this; + + try { + filein >> *this; + } + catch (std::exception &e) { + return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); + } // Return file pointer if (pfileRet) @@ -969,7 +975,12 @@ public: filein.nType |= SER_BLOCKHEADERONLY; // Read block - filein >> *this; + try { + filein >> *this; + } + catch (std::exception &e) { + return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); + } // Check the header if (!CheckProofOfWork(GetHash(), nBits))