diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 21 | ||||
| -rw-r--r-- | src/btfaddr.cpp | 3 | ||||
| -rw-r--r-- | src/main.cpp | 16 | ||||
| -rw-r--r-- | src/main.h | 14 | ||||
| -rw-r--r-- | src/makefile.mingw | 9 | ||||
| -rw-r--r-- | src/net.cpp | 2 | ||||
| -rw-r--r-- | src/net.h | 4 | ||||
| -rw-r--r-- | src/nostr.cpp | 6 | ||||
| -rw-r--r-- | src/util.cpp | 4 | ||||
| -rw-r--r-- | src/util.h | 44 |
10 files changed, 92 insertions, 31 deletions
diff --git a/src/Makefile b/src/Makefile index 9846d8e..f0c6706 100644 --- a/src/Makefile +++ b/src/Makefile | |||
| @@ -9,7 +9,26 @@ RANDOMX_DIR ?= $(HOME)/RandomX | |||
| 9 | 9 | ||
| 10 | IMGUI_DIR = imgui | 10 | IMGUI_DIR = imgui |
| 11 | 11 | ||
| 12 | CXXFLAGS = -std=gnu++14 -O2 -w -fpermissive -pthread \ | 12 | # -w used to sit here and suppressed every diagnostic in the build, including |
| 13 | # the one that mattered: `%I64d` is MSVC-only, glibc mis-parses it as the GNU | ||
| 14 | # `I` flag with a width of 64 and an `int` conversion, and the resulting vararg | ||
| 15 | # desynchronisation segfaulted the node while logging a received block (issue | ||
| 16 | # #5, deterministic at height 1062 -- the first block carrying a real | ||
| 17 | # transaction). GCC had been reporting it all along: | ||
| 18 | # | ||
| 19 | # warning: format '%d' expects argument of type 'int', | ||
| 20 | # but argument 4 has type 'int64_t' | ||
| 21 | # | ||
| 22 | # -w cannot be narrowed: it wins over any -W or -Werror= that follows it, so it | ||
| 23 | # has to go. The four -Wno- entries below are the categories this 2009-era tree | ||
| 24 | # genuinely produces (measured: 248 deprecated-declarations, 157 write-strings, | ||
| 25 | # 18 narrowing, 1 unused-result); silencing them by name instead of silencing | ||
| 26 | # everything keeps the build quiet while leaving format errors fatal. | ||
| 27 | WARNFLAGS = -Wformat -Werror=format \ | ||
| 28 | -Wno-deprecated-declarations -Wno-write-strings \ | ||
| 29 | -Wno-narrowing -Wno-unused-result | ||
| 30 | |||
| 31 | CXXFLAGS = -std=gnu++14 -O2 $(WARNFLAGS) -fpermissive -pthread \ | ||
| 13 | -DSECP256K1_STATIC \ | 32 | -DSECP256K1_STATIC \ |
| 14 | -I$(SECP_INC) -I$(RANDOMX_DIR)/src \ | 33 | -I$(SECP_INC) -I$(RANDOMX_DIR)/src \ |
| 15 | -I/usr/include/nlohmann \ | 34 | -I/usr/include/nlohmann \ |
diff --git a/src/btfaddr.cpp b/src/btfaddr.cpp index 55bb6c5..6edcc91 100644 --- a/src/btfaddr.cpp +++ b/src/btfaddr.cpp | |||
| @@ -7,7 +7,10 @@ | |||
| 7 | #include "btfaddr.h" | 7 | #include "btfaddr.h" |
| 8 | 8 | ||
| 9 | #include <openssl/sha.h> | 9 | #include <openssl/sha.h> |
| 10 | // See the note in nostr.cpp: the makefiles pass -DSECP256K1_STATIC too. | ||
| 11 | #ifndef SECP256K1_STATIC | ||
| 10 | #define SECP256K1_STATIC | 12 | #define SECP256K1_STATIC |
| 13 | #endif | ||
| 11 | #include <secp256k1.h> | 14 | #include <secp256k1.h> |
| 12 | #include <secp256k1_schnorrsig.h> | 15 | #include <secp256k1_schnorrsig.h> |
| 13 | #include <secp256k1_extrakeys.h> | 16 | #include <secp256k1_extrakeys.h> |
diff --git a/src/main.cpp b/src/main.cpp index bb317d2..c882b0b 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -898,7 +898,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo | |||
| 898 | } | 898 | } |
| 899 | 899 | ||
| 900 | if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size()) | 900 | if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size()) |
| 901 | return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size()); | 901 | return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, (int)txPrev.vout.size(), (int)txindex.vSpent.size()); |
| 902 | 902 | ||
| 903 | // If prev is coinbase, check that it's matured | 903 | // If prev is coinbase, check that it's matured |
| 904 | if (txPrev.IsCoinBase()) | 904 | if (txPrev.IsCoinBase()) |
| @@ -1690,14 +1690,14 @@ void PrintBlockTree() | |||
| 1690 | pindex->nBlockPos, | 1690 | pindex->nBlockPos, |
| 1691 | block.GetHash().ToString().substr(0,14).c_str(), | 1691 | block.GetHash().ToString().substr(0,14).c_str(), |
| 1692 | DateTimeStr(block.nTime).c_str(), | 1692 | DateTimeStr(block.nTime).c_str(), |
| 1693 | block.vtx.size()); | 1693 | (int)block.vtx.size()); |
| 1694 | 1694 | ||
| 1695 | CRITICAL_BLOCK(cs_mapWallet) | 1695 | CRITICAL_BLOCK(cs_mapWallet) |
| 1696 | { | 1696 | { |
| 1697 | if (mapWallet.count(block.vtx[0].GetHash())) | 1697 | if (mapWallet.count(block.vtx[0].GetHash())) |
| 1698 | { | 1698 | { |
| 1699 | CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()]; | 1699 | CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()]; |
| 1700 | printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); | 1700 | printf(" mine: %d %d %lld", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); |
| 1701 | } | 1701 | } |
| 1702 | } | 1702 | } |
| 1703 | printf("\n"); | 1703 | printf("\n"); |
| @@ -1759,7 +1759,7 @@ bool ProcessMessages(CNode* pfrom) | |||
| 1759 | CDataStream& vRecv = pfrom->vRecv; | 1759 | CDataStream& vRecv = pfrom->vRecv; |
| 1760 | if (vRecv.empty()) | 1760 | if (vRecv.empty()) |
| 1761 | return true; | 1761 | return true; |
| 1762 | LogPrint("net", "ProcessMessages(%d bytes)\n", vRecv.size()); | 1762 | LogPrint("net", "ProcessMessages(%d bytes)\n", (int)vRecv.size()); |
| 1763 | 1763 | ||
| 1764 | // | 1764 | // |
| 1765 | // Message format | 1765 | // Message format |
| @@ -1783,7 +1783,7 @@ bool ProcessMessages(CNode* pfrom) | |||
| 1783 | break; | 1783 | break; |
| 1784 | } | 1784 | } |
| 1785 | if (pstart - vRecv.begin() > 0) | 1785 | if (pstart - vRecv.begin() > 0) |
| 1786 | if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", pstart - vRecv.begin()); | 1786 | if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", (int)(pstart - vRecv.begin())); |
| 1787 | vRecv.erase(vRecv.begin(), pstart); | 1787 | vRecv.erase(vRecv.begin(), pstart); |
| 1788 | 1788 | ||
| 1789 | // Read header | 1789 | // Read header |
| @@ -1836,7 +1836,7 @@ bool ProcessMessages(CNode* pfrom) | |||
| 1836 | bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | 1836 | bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) |
| 1837 | { | 1837 | { |
| 1838 | static map<unsigned int, vector<unsigned char> > mapReuseKey; | 1838 | static map<unsigned int, vector<unsigned char> > mapReuseKey; |
| 1839 | if (LogAcceptsCategory("net")) { printf("received: %-12s (%d bytes) ", strCommand.c_str(), vRecv.size()); for (int i = 0; i < min(vRecv.size(), (unsigned int)25); i++) printf("%02x ", vRecv[i] & 0xff); printf("\n"); } | 1839 | if (LogAcceptsCategory("net")) { printf("received: %-12s (%d bytes) ", strCommand.c_str(), (int)vRecv.size()); for (int i = 0; i < min(vRecv.size(), (unsigned int)25); i++) printf("%02x ", vRecv[i] & 0xff); printf("\n"); } |
| 1840 | if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) | 1840 | if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) |
| 1841 | { | 1841 | { |
| 1842 | if (LogAcceptsCategory("net")) printf("dropmessages DROPPING RECV MESSAGE\n"); | 1842 | if (LogAcceptsCategory("net")) printf("dropmessages DROPPING RECV MESSAGE\n"); |
| @@ -2171,7 +2171,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) | |||
| 2171 | 2171 | ||
| 2172 | 2172 | ||
| 2173 | if (!vRecv.empty()) | 2173 | if (!vRecv.empty()) |
| 2174 | if (LogAcceptsCategory("net")) printf("ProcessMessage(%s) : %d extra bytes\n", strCommand.c_str(), vRecv.size()); | 2174 | if (LogAcceptsCategory("net")) printf("ProcessMessage(%s) : %d extra bytes\n", strCommand.c_str(), (int)vRecv.size()); |
| 2175 | 2175 | ||
| 2176 | return true; | 2176 | return true; |
| 2177 | } | 2177 | } |
| @@ -2885,7 +2885,7 @@ bool BitcoinMiner() | |||
| 2885 | } | 2885 | } |
| 2886 | pblock->nBits = nBits; | 2886 | pblock->nBits = nBits; |
| 2887 | pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nBestHeight + 1, nFees); | 2887 | pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nBestHeight + 1, nFees); |
| 2888 | if (LogAcceptsCategory("net")) printf("\n\nRunning BitcoinMiner with %d transactions in block\n", pblock->vtx.size()); | 2888 | if (LogAcceptsCategory("net")) printf("\n\nRunning BitcoinMiner with %d transactions in block\n", (int)pblock->vtx.size()); |
| 2889 | 2889 | ||
| 2890 | 2890 | ||
| 2891 | // | 2891 | // |
| @@ -650,11 +650,11 @@ public: | |||
| 650 | string ToString() const | 650 | string ToString() const |
| 651 | { | 651 | { |
| 652 | string str; | 652 | string str; |
| 653 | str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n", | 653 | str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%u)\n", |
| 654 | GetHash().ToString().substr(0,6).c_str(), | 654 | GetHash().ToString().substr(0,6).c_str(), |
| 655 | nVersion, | 655 | nVersion, |
| 656 | vin.size(), | 656 | (int)vin.size(), |
| 657 | vout.size(), | 657 | (int)vout.size(), |
| 658 | nLockTime); | 658 | nLockTime); |
| 659 | for (int i = 0; i < vin.size(); i++) | 659 | for (int i = 0; i < vin.size(); i++) |
| 660 | str += " " + vin[i].ToString() + "\n"; | 660 | str += " " + vin[i].ToString() + "\n"; |
| @@ -1081,7 +1081,7 @@ public: | |||
| 1081 | hashPrevBlock.ToString().substr(0,14).c_str(), | 1081 | hashPrevBlock.ToString().substr(0,14).c_str(), |
| 1082 | hashMerkleRoot.ToString().substr(0,6).c_str(), | 1082 | hashMerkleRoot.ToString().substr(0,6).c_str(), |
| 1083 | nTime, nBits, nNonce, | 1083 | nTime, nBits, nNonce, |
| 1084 | vtx.size()); | 1084 | (int)vtx.size()); |
| 1085 | for (int i = 0; i < vtx.size(); i++) | 1085 | for (int i = 0; i < vtx.size(); i++) |
| 1086 | { | 1086 | { |
| 1087 | printf(" "); | 1087 | printf(" "); |
| @@ -1223,8 +1223,10 @@ public: | |||
| 1223 | 1223 | ||
| 1224 | string ToString() const | 1224 | string ToString() const |
| 1225 | { | 1225 | { |
| 1226 | return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)", | 1226 | // pprev/pnext are pointers: %08x truncated them to 32 bits on a 64-bit |
| 1227 | pprev, pnext, nFile, nBlockPos, nHeight, | 1227 | // build, so the two fields this line exists to show were unreliable. |
| 1228 | return strprintf("CBlockIndex(nprev=%p, pnext=%p, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)", | ||
| 1229 | (void*)pprev, (void*)pnext, nFile, nBlockPos, nHeight, | ||
| 1228 | hashMerkleRoot.ToString().substr(0,6).c_str(), | 1230 | hashMerkleRoot.ToString().substr(0,6).c_str(), |
| 1229 | GetBlockHash().ToString().substr(0,14).c_str()); | 1231 | GetBlockHash().ToString().substr(0,14).c_str()); |
| 1230 | } | 1232 | } |
diff --git a/src/makefile.mingw b/src/makefile.mingw index 7d35d92..01f7702 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw | |||
| @@ -7,7 +7,14 @@ DEPS = ../deps | |||
| 7 | RANDOMX = ../RandomX | 7 | RANDOMX = ../RandomX |
| 8 | IMGUI_DIR = imgui | 8 | IMGUI_DIR = imgui |
| 9 | 9 | ||
| 10 | CXXFLAGS = -std=gnu++14 -O2 -w -fpermissive -Wno-deprecated-declarations -pthread \ | 10 | # See the long note in Makefile: -w hid the format bug that segfaulted the node |
| 11 | # on glibc (issue #5), and -w cannot be narrowed, so format diagnostics are now | ||
| 12 | # fatal and only the categories this tree actually produces are silenced. | ||
| 13 | WARNFLAGS = -Wformat -Werror=format \ | ||
| 14 | -Wno-deprecated-declarations -Wno-write-strings \ | ||
| 15 | -Wno-narrowing -Wno-unused-result | ||
| 16 | |||
| 17 | CXXFLAGS = -std=gnu++14 -O2 $(WARNFLAGS) -fpermissive -pthread \ | ||
| 11 | -DWIN32 -DNOPCH \ | 18 | -DWIN32 -DNOPCH \ |
| 12 | -DSECP256K1_STATIC \ | 19 | -DSECP256K1_STATIC \ |
| 13 | -I$(DEPS)/include -I$(RANDOMX)/src \ | 20 | -I$(DEPS)/include -I$(RANDOMX)/src \ |
diff --git a/src/net.cpp b/src/net.cpp index 08a3348..395092d 100644 --- a/src/net.cpp +++ b/src/net.cpp | |||
| @@ -920,7 +920,7 @@ void ThreadSocketHandler2(void* parg) | |||
| 920 | 920 | ||
| 921 | if (pnodeExtra->GetRefCount() <= (pnodeExtra->fNetworkNode ? 1 : 0)) | 921 | if (pnodeExtra->GetRefCount() <= (pnodeExtra->fNetworkNode ? 1 : 0)) |
| 922 | { | 922 | { |
| 923 | LogPrint("net", "(%d nodes) disconnecting duplicate: %s\n", vNodes.size(), pnodeExtra->addr.ToString().c_str()); | 923 | LogPrint("net", "(%d nodes) disconnecting duplicate: %s\n", (int)vNodes.size(), pnodeExtra->addr.ToString().c_str()); |
| 924 | if (pnodeExtra->fNetworkNode && !pnode->fNetworkNode) | 924 | if (pnodeExtra->fNetworkNode && !pnode->fNetworkNode) |
| 925 | { | 925 | { |
| 926 | pnode->AddRef(); | 926 | pnode->AddRef(); |
| @@ -392,7 +392,9 @@ public: | |||
| 392 | const char* GetCommand() const | 392 | const char* GetCommand() const |
| 393 | { | 393 | { |
| 394 | if (!IsKnownType()) | 394 | if (!IsKnownType()) |
| 395 | throw std::out_of_range(strprintf("CInv::GetCommand() : type=% unknown type", type)); | 395 | // Was "type=% unknown type": the % swallowed the space as a flag and |
| 396 | // the u as the conversion, so this read "type= 3nknown type". | ||
| 397 | throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type)); | ||
| 396 | return ppszTypeName[type]; | 398 | return ppszTypeName[type]; |
| 397 | } | 399 | } |
| 398 | 400 | ||
diff --git a/src/nostr.cpp b/src/nostr.cpp index 482a835..088174a 100644 --- a/src/nostr.cpp +++ b/src/nostr.cpp | |||
| @@ -6,8 +6,12 @@ | |||
| 6 | #include "headers.h" | 6 | #include "headers.h" |
| 7 | #include <openssl/ssl.h> | 7 | #include <openssl/ssl.h> |
| 8 | #include <openssl/err.h> | 8 | #include <openssl/err.h> |
| 9 | // We link libsecp256k1 statically (without this the header assumes DLL import) | 9 | // We link libsecp256k1 statically (without this the header assumes DLL import). |
| 10 | // Both makefiles also pass -DSECP256K1_STATIC; the guard keeps that from | ||
| 11 | // warning while leaving this file correct if built without the flag. | ||
| 12 | #ifndef SECP256K1_STATIC | ||
| 10 | #define SECP256K1_STATIC | 13 | #define SECP256K1_STATIC |
| 14 | #endif | ||
| 11 | #include <secp256k1.h> | 15 | #include <secp256k1.h> |
| 12 | #include <secp256k1_schnorrsig.h> | 16 | #include <secp256k1_schnorrsig.h> |
| 13 | #include <secp256k1_extrakeys.h> | 17 | #include <secp256k1_extrakeys.h> |
diff --git a/src/util.cpp b/src/util.cpp index e4e314f..d52ca88 100644 --- a/src/util.cpp +++ b/src/util.cpp | |||
| @@ -180,7 +180,7 @@ void RandAddSeed(bool fPerfmon) | |||
| 180 | RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash))); | 180 | RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash))); |
| 181 | hash = 0; | 181 | hash = 0; |
| 182 | memset(pdata, 0, nSize); | 182 | memset(pdata, 0, nSize); |
| 183 | printf("RandAddSeed() got %d bytes of performance data\n", nSize); | 183 | printf("RandAddSeed() got %lu bytes of performance data\n", nSize); |
| 184 | } | 184 | } |
| 185 | } | 185 | } |
| 186 | #else | 186 | #else |
| @@ -472,7 +472,7 @@ void AddTimeData(unsigned int ip, int64 nTime) | |||
| 472 | if (vTimeOffsets.empty()) | 472 | if (vTimeOffsets.empty()) |
| 473 | vTimeOffsets.push_back(0); | 473 | vTimeOffsets.push_back(0); |
| 474 | vTimeOffsets.push_back(nOffsetSample); | 474 | vTimeOffsets.push_back(nOffsetSample); |
| 475 | printf("Added time data, samples %d, ip %08x, offset %+lld (%+lld minutes)\n", vTimeOffsets.size(), ip, vTimeOffsets.back(), vTimeOffsets.back()/60); | 475 | printf("Added time data, samples %d, ip %08x, offset %+lld (%+lld minutes)\n", (int)vTimeOffsets.size(), ip, vTimeOffsets.back(), vTimeOffsets.back()/60); |
| 476 | if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) | 476 | if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) |
| 477 | { | 477 | { |
| 478 | sort(vTimeOffsets.begin(), vTimeOffsets.end()); | 478 | sort(vTimeOffsets.begin(), vTimeOffsets.end()); |
| @@ -14,7 +14,9 @@ typedef unsigned long long uint64; | |||
| 14 | #define for if (false) ; else for | 14 | #define for if (false) ; else for |
| 15 | #endif | 15 | #endif |
| 16 | 16 | ||
| 17 | #ifndef _MSC_VER | 17 | // MinGW already provides __forceinline for MSVC compatibility, so defining it |
| 18 | // unconditionally warned ten times per build once -w was removed. | ||
| 19 | #if !defined(_MSC_VER) && !defined(__forceinline) | ||
| 18 | #define __forceinline inline | 20 | #define __forceinline inline |
| 19 | #endif | 21 | #endif |
| 20 | 22 | ||
| @@ -40,17 +42,17 @@ typedef unsigned long long uint64; | |||
| 40 | #endif | 42 | #endif |
| 41 | #define snprintf my_snprintf | 43 | #define snprintf my_snprintf |
| 42 | 44 | ||
| 45 | // One definition for every target. The MSVCRT branch that used to sit here | ||
| 46 | // produced "I64d", which is the specifier that segfaults on glibc (issue #5) -- | ||
| 47 | // and it was pointless besides: this build targets UCRT, which accepts the C99 | ||
| 48 | // forms, and the rest of the tree already prints int64 with %lld on Windows. | ||
| 49 | // Keeping one spelling everywhere is also what lets the format attributes below | ||
| 50 | // use a single archetype, so a bad specifier fails the build on both platforms. | ||
| 43 | #ifndef PRId64 | 51 | #ifndef PRId64 |
| 44 | #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MSVCRT__) | ||
| 45 | #define PRId64 "I64d" | ||
| 46 | #define PRIu64 "I64u" | ||
| 47 | #define PRIx64 "I64x" | ||
| 48 | #else | ||
| 49 | #define PRId64 "lld" | 52 | #define PRId64 "lld" |
| 50 | #define PRIu64 "llu" | 53 | #define PRIu64 "llu" |
| 51 | #define PRIx64 "llx" | 54 | #define PRIx64 "llx" |
| 52 | #endif | 55 | #endif |
| 53 | #endif | ||
| 54 | 56 | ||
| 55 | // This is needed because the foreach macro can't get over the comma in pair<t1, t2> | 57 | // This is needed because the foreach macro can't get over the comma in pair<t1, t2> |
| 56 | #define PAIRTYPE(t1, t2) pair<t1, t2> | 58 | #define PAIRTYPE(t1, t2) pair<t1, t2> |
| @@ -102,10 +104,30 @@ void LogPrintDedup(const char* category, const char* file, int line, const std:: | |||
| 102 | #define LogPrint(category, ...) \ | 104 | #define LogPrint(category, ...) \ |
| 103 | do { if (LogAcceptsCategory(category)) LogPrintDedup((category), __FILE__, __LINE__, strprintf(__VA_ARGS__)); } while (0) | 105 | do { if (LogAcceptsCategory(category)) LogPrintDedup((category), __FILE__, __LINE__, strprintf(__VA_ARGS__)); } while (0) |
| 104 | 106 | ||
| 107 | // Every format string in this project goes through one of the four functions | ||
| 108 | // below -- `printf` itself is remapped to OutputDebugStringF just above, and | ||
| 109 | // snprintf to my_snprintf. None of them carried a format attribute, and GCC | ||
| 110 | // only checks format strings for functions it knows are printf-like, so | ||
| 111 | // -Wformat had nothing to inspect and the whole tree was unchecked. That is | ||
| 112 | // how `%I64d` (MSVC-only, and a segfault on glibc) survived in | ||
| 113 | // CTxOut::ToString until it crashed a node mid-sync -- see issue #5. | ||
| 114 | // | ||
| 115 | // gnu_printf on both platforms, deliberately. MinGW's other option, ms_printf, | ||
| 116 | // models the legacy msvcrt: it rejects %zu, which this tree uses and UCRT | ||
| 117 | // supports, and it accepts %I64d, which is the specifier that crashes on glibc. | ||
| 118 | // It would give false positives where the code is right and stay silent where it | ||
| 119 | // is dangerous. gnu_printf describes UCRT's C99 behaviour accurately, so one | ||
| 120 | // archetype covers both builds and a bad specifier fails either one. | ||
| 121 | #if defined(__GNUC__) | ||
| 122 | #define BF_FORMAT(fmt, args) __attribute__((format(gnu_printf, fmt, args))) | ||
| 123 | #else | ||
| 124 | #define BF_FORMAT(fmt, args) | ||
| 125 | #endif | ||
| 126 | |||
| 105 | void RandAddSeed(bool fPerfmon=false); | 127 | void RandAddSeed(bool fPerfmon=false); |
| 106 | int my_snprintf(char* buffer, size_t limit, const char* format, ...); | 128 | int my_snprintf(char* buffer, size_t limit, const char* format, ...) BF_FORMAT(3, 4); |
| 107 | string strprintf(const char* format, ...); | 129 | string strprintf(const char* format, ...) BF_FORMAT(1, 2); |
| 108 | bool error(const char* format, ...); | 130 | bool error(const char* format, ...) BF_FORMAT(1, 2); |
| 109 | void PrintException(std::exception* pex, const char* pszThread); | 131 | void PrintException(std::exception* pex, const char* pszThread); |
| 110 | void ParseString(const string& str, char c, vector<string>& v); | 132 | void ParseString(const string& str, char c, vector<string>& v); |
| 111 | string FormatMoney(int64 n, bool fPlus=false); | 133 | string FormatMoney(int64 n, bool fPlus=false); |
| @@ -266,6 +288,8 @@ void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSp | |||
| 266 | // Forward declaration -- defined in main.cpp | 288 | // Forward declaration -- defined in main.cpp |
| 267 | string GetAppDir(); | 289 | string GetAppDir(); |
| 268 | 290 | ||
| 291 | inline int OutputDebugStringF(const char* pszFormat, ...) BF_FORMAT(1, 2); | ||
| 292 | |||
| 269 | inline int OutputDebugStringF(const char* pszFormat, ...) | 293 | inline int OutputDebugStringF(const char* pszFormat, ...) |
| 270 | { | 294 | { |
| 271 | #if 1 // debug.log always enabled | 295 | #if 1 // debug.log always enabled |