Merge #9512: Fix various things -fsanitize complains about

82e8baa Avoid boost dynamic_bitset in rest_getutxos (Pieter Wuille)
99f001e Fix memory leak in multiUserAuthorized (Pieter Wuille)
5a0b7e4 Fix memory leak in net_tests (Pieter Wuille)
6b03bfb Fix memory leak in wallet tests (Pieter Wuille)
f94f3e0 Avoid integer overflows in scriptnum tests (Pieter Wuille)
843c560 Avoid unaligned access in crypto i/o (Pieter Wuille)
This commit is contained in:
Wladimir J. van der Laan 2017-01-18 19:24:02 +01:00
commit 6012967c47
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
6 changed files with 49 additions and 25 deletions

View File

@ -10,57 +10,73 @@
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include "compat/endian.h" #include "compat/endian.h"
uint16_t static inline ReadLE16(const unsigned char* ptr) uint16_t static inline ReadLE16(const unsigned char* ptr)
{ {
return le16toh(*((uint16_t*)ptr)); uint16_t x;
memcpy((char*)&x, ptr, 2);
return le16toh(x);
} }
uint32_t static inline ReadLE32(const unsigned char* ptr) uint32_t static inline ReadLE32(const unsigned char* ptr)
{ {
return le32toh(*((uint32_t*)ptr)); uint32_t x;
memcpy((char*)&x, ptr, 4);
return le32toh(x);
} }
uint64_t static inline ReadLE64(const unsigned char* ptr) uint64_t static inline ReadLE64(const unsigned char* ptr)
{ {
return le64toh(*((uint64_t*)ptr)); uint64_t x;
memcpy((char*)&x, ptr, 8);
return le64toh(x);
} }
void static inline WriteLE16(unsigned char* ptr, uint16_t x) void static inline WriteLE16(unsigned char* ptr, uint16_t x)
{ {
*((uint16_t*)ptr) = htole16(x); uint16_t v = htole16(x);
memcpy(ptr, (char*)&v, 2);
} }
void static inline WriteLE32(unsigned char* ptr, uint32_t x) void static inline WriteLE32(unsigned char* ptr, uint32_t x)
{ {
*((uint32_t*)ptr) = htole32(x); uint32_t v = htole32(x);
memcpy(ptr, (char*)&v, 4);
} }
void static inline WriteLE64(unsigned char* ptr, uint64_t x) void static inline WriteLE64(unsigned char* ptr, uint64_t x)
{ {
*((uint64_t*)ptr) = htole64(x); uint64_t v = htole64(x);
memcpy(ptr, (char*)&v, 8);
} }
uint32_t static inline ReadBE32(const unsigned char* ptr) uint32_t static inline ReadBE32(const unsigned char* ptr)
{ {
return be32toh(*((uint32_t*)ptr)); uint32_t x;
memcpy((char*)&x, ptr, 4);
return be32toh(x);
} }
uint64_t static inline ReadBE64(const unsigned char* ptr) uint64_t static inline ReadBE64(const unsigned char* ptr)
{ {
return be64toh(*((uint64_t*)ptr)); uint64_t x;
memcpy((char*)&x, ptr, 8);
return be64toh(x);
} }
void static inline WriteBE32(unsigned char* ptr, uint32_t x) void static inline WriteBE32(unsigned char* ptr, uint32_t x)
{ {
*((uint32_t*)ptr) = htobe32(x); uint32_t v = htobe32(x);
memcpy(ptr, (char*)&v, 4);
} }
void static inline WriteBE64(unsigned char* ptr, uint64_t x) void static inline WriteBE64(unsigned char* ptr, uint64_t x)
{ {
*((uint64_t*)ptr) = htobe64(x); uint64_t v = htobe64(x);
memcpy(ptr, (char*)&v, 8);
} }
#endif // BITCOIN_CRYPTO_COMMON_H #endif // BITCOIN_CRYPTO_COMMON_H

View File

@ -113,8 +113,8 @@ static bool multiUserAuthorized(std::string strUserPass)
std::string strHash = vFields[2]; std::string strHash = vFields[2];
unsigned int KEY_SIZE = 32; unsigned int KEY_SIZE = 32;
unsigned char *out = new unsigned char[KEY_SIZE]; unsigned char out[KEY_SIZE];
CHMAC_SHA256(reinterpret_cast<const unsigned char*>(strSalt.c_str()), strSalt.size()).Write(reinterpret_cast<const unsigned char*>(strPass.c_str()), strPass.size()).Finalize(out); CHMAC_SHA256(reinterpret_cast<const unsigned char*>(strSalt.c_str()), strSalt.size()).Write(reinterpret_cast<const unsigned char*>(strPass.c_str()), strPass.size()).Finalize(out);
std::vector<unsigned char> hexvec(out, out+KEY_SIZE); std::vector<unsigned char> hexvec(out, out+KEY_SIZE);
std::string strHashFromPass = HexStr(hexvec); std::string strHashFromPass = HexStr(hexvec);

View File

@ -17,7 +17,6 @@
#include "version.h" #include "version.h"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/dynamic_bitset.hpp>
#include <univalue.h> #include <univalue.h>
@ -502,7 +501,8 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
vector<unsigned char> bitmap; vector<unsigned char> bitmap;
vector<CCoin> outs; vector<CCoin> outs;
std::string bitmapStringRepresentation; std::string bitmapStringRepresentation;
boost::dynamic_bitset<unsigned char> hits(vOutPoints.size()); std::vector<bool> hits;
bitmap.resize((vOutPoints.size() + 7) / 8);
{ {
LOCK2(cs_main, mempool.cs); LOCK2(cs_main, mempool.cs);
@ -518,10 +518,11 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
for (size_t i = 0; i < vOutPoints.size(); i++) { for (size_t i = 0; i < vOutPoints.size(); i++) {
CCoins coins; CCoins coins;
uint256 hash = vOutPoints[i].hash; uint256 hash = vOutPoints[i].hash;
bool hit = false;
if (view.GetCoins(hash, coins)) { if (view.GetCoins(hash, coins)) {
mempool.pruneSpent(hash, coins); mempool.pruneSpent(hash, coins);
if (coins.IsAvailable(vOutPoints[i].n)) { if (coins.IsAvailable(vOutPoints[i].n)) {
hits[i] = true; hit = true;
// Safe to index into vout here because IsAvailable checked if it's off the end of the array, or if // Safe to index into vout here because IsAvailable checked if it's off the end of the array, or if
// n is valid but points to an already spent output (IsNull). // n is valid but points to an already spent output (IsNull).
CCoin coin; CCoin coin;
@ -533,10 +534,11 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
} }
} }
bitmapStringRepresentation.append(hits[i] ? "1" : "0"); // form a binary string representation (human-readable for json output) hits.push_back(hit);
bitmapStringRepresentation.append(hit ? "1" : "0"); // form a binary string representation (human-readable for json output)
bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
} }
} }
boost::to_block_range(hits, std::back_inserter(bitmap));
switch (rf) { switch (rf) {
case RF_BINARY: { case RF_BINARY: {

View File

@ -162,12 +162,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
bool fInboundIn = false; bool fInboundIn = false;
// Test that fFeeler is false by default. // Test that fFeeler is false by default.
CNode* pnode1 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, pszDest, fInboundIn); std::unique_ptr<CNode> pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, pszDest, fInboundIn));
BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fInbound == false);
BOOST_CHECK(pnode1->fFeeler == false); BOOST_CHECK(pnode1->fFeeler == false);
fInboundIn = true; fInboundIn = true;
CNode* pnode2 = new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, pszDest, fInboundIn); std::unique_ptr<CNode> pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, pszDest, fInboundIn));
BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fInbound == true);
BOOST_CHECK(pnode2->fFeeler == false); BOOST_CHECK(pnode2->fFeeler == false);
} }

View File

@ -12,8 +12,10 @@
BOOST_FIXTURE_TEST_SUITE(scriptnum_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(scriptnum_tests, BasicTestingSetup)
static const int64_t values[] = \ /** A selection of numbers that do not trigger int64_t overflow
{ 0, 1, CHAR_MIN, CHAR_MAX, UCHAR_MAX, SHRT_MIN, USHRT_MAX, INT_MIN, INT_MAX, UINT_MAX, LONG_MIN, LONG_MAX }; * when added/subtracted. */
static const int64_t values[] = { 0, 1, -2, 127, 128, -255, 256, (1LL << 15) - 1, -(1LL << 16), (1LL << 24) - 1, (1LL << 31), 1 - (1LL << 32), 1LL << 40 };
static const int64_t offsets[] = { 1, 0x79, 0x80, 0x81, 0xFF, 0x7FFF, 0x8000, 0xFFFF, 0x10000}; static const int64_t offsets[] = { 1, 0x79, 0x80, 0x81, 0xFF, 0x7FFF, 0x8000, 0xFFFF, 0x10000};
static bool verify(const CScriptNum10& bignum, const CScriptNum& scriptnum) static bool verify(const CScriptNum10& bignum, const CScriptNum& scriptnum)

View File

@ -23,6 +23,8 @@
using namespace std; using namespace std;
std::vector<std::unique_ptr<CWalletTx>> wtxn;
typedef set<pair<const CWalletTx*,unsigned int> > CoinSet; typedef set<pair<const CWalletTx*,unsigned int> > CoinSet;
BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup) BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
@ -42,21 +44,21 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa
// so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe() // so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
tx.vin.resize(1); tx.vin.resize(1);
} }
CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx))); std::unique_ptr<CWalletTx> wtx(new CWalletTx(&wallet, MakeTransactionRef(std::move(tx))));
if (fIsFromMe) if (fIsFromMe)
{ {
wtx->fDebitCached = true; wtx->fDebitCached = true;
wtx->nDebitCached = 1; wtx->nDebitCached = 1;
} }
COutput output(wtx, nInput, nAge, true, true); COutput output(wtx.get(), nInput, nAge, true, true);
vCoins.push_back(output); vCoins.push_back(output);
wtxn.emplace_back(std::move(wtx));
} }
static void empty_wallet(void) static void empty_wallet(void)
{ {
BOOST_FOREACH(COutput output, vCoins)
delete output.tx;
vCoins.clear(); vCoins.clear();
wtxn.clear();
} }
static bool equal_sets(CoinSet a, CoinSet b) static bool equal_sets(CoinSet a, CoinSet b)
@ -349,6 +351,8 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
BOOST_CHECK(wallet.SelectCoinsMinConf(1003 * COIN, 1, 6, 0, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK(wallet.SelectCoinsMinConf(1003 * COIN, 1, 6, 0, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1003 * COIN); BOOST_CHECK_EQUAL(nValueRet, 1003 * COIN);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U);
empty_wallet();
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()