Merge #14835: [0.17] Further Backports
f9db08e8ca
qa: Avoid race in p2p_invalid_block by waiting for the block request (MarcoFalke)79358817e5
Add SAFE_CHARS[SAFE_CHARS_URI]: Chars allowed in URIs (RFC 3986) (practicalswift)9666dbaf09
rpc: Make HTTP RPC debug logging more informative (practicalswift)b90157891a
add test demonstrating addrLocal UB (Kaz Wesley)6f04264bbb
fix uninitialized read when stringifying an addrLocal (Kaz Wesley)5782fdcd8c
Throw error if CPubKey is invalid during PSBT keypath serialization (Gregory Sanders)de5e48a461
Bugfix: RPC: Add address_type named param for createmultisig (Luke Dashjr)df5131bd41
gui: explicitly disable "Dark Mode" appearance on macOS (fanquake) Pull request description: Backports #14593, #14596, #14618, #14690 and #14728 to the 0.17 branch. Tree-SHA512: fcda4b75fcb71bb80cc8bde2a2b98ff5c0239dfa754ac980b1a91a90409502ac7678326399a4fc03a773074339dbf8b3d11750c91fe4302741a954745acfcca1
This commit is contained in:
commit
d8bc0ce1da
10 changed files with 59 additions and 10 deletions
|
@ -99,6 +99,9 @@
|
||||||
|
|
||||||
<key>LSAppNapIsDisabled</key>
|
<key>LSAppNapIsDisabled</key>
|
||||||
<string>True</string>
|
<string>True</string>
|
||||||
|
|
||||||
|
<key>NSRequiresAquaSystemAppearance</key>
|
||||||
|
<string>True</string>
|
||||||
|
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.finance</string>
|
<string>public.app-category.finance</string>
|
||||||
|
|
|
@ -224,21 +224,25 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
|
||||||
}
|
}
|
||||||
std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
|
std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
|
||||||
|
|
||||||
LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
|
|
||||||
RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString());
|
|
||||||
|
|
||||||
// Early address-based allow check
|
// Early address-based allow check
|
||||||
if (!ClientAllowed(hreq->GetPeer())) {
|
if (!ClientAllowed(hreq->GetPeer())) {
|
||||||
|
LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Client network is not allowed RPC access\n",
|
||||||
|
hreq->GetPeer().ToString());
|
||||||
hreq->WriteReply(HTTP_FORBIDDEN);
|
hreq->WriteReply(HTTP_FORBIDDEN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Early reject unknown HTTP methods
|
// Early reject unknown HTTP methods
|
||||||
if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
|
if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
|
||||||
|
LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Unknown HTTP request method\n",
|
||||||
|
hreq->GetPeer().ToString());
|
||||||
hreq->WriteReply(HTTP_BADMETHOD);
|
hreq->WriteReply(HTTP_BADMETHOD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
|
||||||
|
RequestMethodString(hreq->GetRequestMethod()), SanitizeString(hreq->GetURI(), SAFE_CHARS_URI).substr(0, 100), hreq->GetPeer().ToString());
|
||||||
|
|
||||||
// Find registered handler for prefix
|
// Find registered handler for prefix
|
||||||
std::string strURI = hreq->GetURI();
|
std::string strURI = hreq->GetURI();
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
|
@ -17,7 +17,6 @@ static const unsigned char g_internal_prefix[] = { 0xFD, 0x6B, 0x88, 0xC0, 0x87,
|
||||||
CNetAddr::CNetAddr()
|
CNetAddr::CNetAddr()
|
||||||
{
|
{
|
||||||
memset(ip, 0, sizeof(ip));
|
memset(ip, 0, sizeof(ip));
|
||||||
scopeId = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNetAddr::SetIP(const CNetAddr& ipIn)
|
void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||||
|
|
|
@ -33,7 +33,7 @@ class CNetAddr
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
unsigned char ip[16]; // in network byte order
|
unsigned char ip[16]; // in network byte order
|
||||||
uint32_t scopeId; // for scoped/link-local ipv6 addresses
|
uint32_t scopeId{0}; // for scoped/link-local ipv6 addresses
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CNetAddr();
|
CNetAddr();
|
||||||
|
|
|
@ -474,7 +474,7 @@ static const CRPCCommand commands[] =
|
||||||
{ "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
|
{ "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
|
||||||
{ "control", "logging", &logging, {"include", "exclude"}},
|
{ "control", "logging", &logging, {"include", "exclude"}},
|
||||||
{ "util", "validateaddress", &validateaddress, {"address"} }, /* uses wallet if enabled */
|
{ "util", "validateaddress", &validateaddress, {"address"} }, /* uses wallet if enabled */
|
||||||
{ "util", "createmultisig", &createmultisig, {"nrequired","keys"} },
|
{ "util", "createmultisig", &createmultisig, {"nrequired","keys","address_type"} },
|
||||||
{ "util", "verifymessage", &verifymessage, {"address","signature","message"} },
|
{ "util", "verifymessage", &verifymessage, {"address","signature","message"} },
|
||||||
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
|
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
|
||||||
|
|
||||||
|
|
|
@ -188,6 +188,9 @@ template<typename Stream>
|
||||||
void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths, uint8_t type)
|
void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, std::vector<uint32_t>>& hd_keypaths, uint8_t type)
|
||||||
{
|
{
|
||||||
for (auto keypath_pair : hd_keypaths) {
|
for (auto keypath_pair : hd_keypaths) {
|
||||||
|
if (!keypath_pair.first.IsValid()) {
|
||||||
|
throw std::ios_base::failure("Invalid CPubKey being serialized");
|
||||||
|
}
|
||||||
SerializeToVector(s, type, MakeSpan(keypath_pair.first));
|
SerializeToVector(s, type, MakeSpan(keypath_pair.first));
|
||||||
WriteCompactSize(s, keypath_pair.second.size() * sizeof(uint32_t));
|
WriteCompactSize(s, keypath_pair.second.size() * sizeof(uint32_t));
|
||||||
for (auto& path : keypath_pair.second) {
|
for (auto& path : keypath_pair.second) {
|
||||||
|
|
|
@ -189,4 +189,42 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
||||||
BOOST_CHECK(pnode2->fFeeler == false);
|
BOOST_CHECK(pnode2->fFeeler == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prior to PR #14728, this test triggers an undefined behavior
|
||||||
|
BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
|
||||||
|
{
|
||||||
|
// set up local addresses; all that's necessary to reproduce the bug is
|
||||||
|
// that a normal IPv4 address is among the entries, but if this address is
|
||||||
|
// !IsRoutable the undefined behavior is easier to trigger deterministically
|
||||||
|
{
|
||||||
|
LOCK(cs_mapLocalHost);
|
||||||
|
in_addr ipv4AddrLocal;
|
||||||
|
ipv4AddrLocal.s_addr = 0x0100007f;
|
||||||
|
CNetAddr addr = CNetAddr(ipv4AddrLocal);
|
||||||
|
LocalServiceInfo lsi;
|
||||||
|
lsi.nScore = 23;
|
||||||
|
lsi.nPort = 42;
|
||||||
|
mapLocalHost[addr] = lsi;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a peer with an IPv4 address
|
||||||
|
in_addr ipv4AddrPeer;
|
||||||
|
ipv4AddrPeer.s_addr = 0xa0b0c001;
|
||||||
|
CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
|
||||||
|
std::unique_ptr<CNode> pnode = MakeUnique<CNode>(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, CAddress{}, std::string{}, false);
|
||||||
|
pnode->fSuccessfullyConnected.store(true);
|
||||||
|
|
||||||
|
// the peer claims to be reaching us via IPv6
|
||||||
|
in6_addr ipv6AddrLocal;
|
||||||
|
memset(ipv6AddrLocal.s6_addr, 0, 16);
|
||||||
|
ipv6AddrLocal.s6_addr[0] = 0xcc;
|
||||||
|
CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK);
|
||||||
|
pnode->SetAddrLocal(addrLocal);
|
||||||
|
|
||||||
|
// before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
|
||||||
|
AdvertiseLocal(&*pnode);
|
||||||
|
|
||||||
|
// suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
|
||||||
|
BOOST_CHECK(1);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
@ -19,6 +19,7 @@ static const std::string SAFE_CHARS[] =
|
||||||
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
|
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
|
||||||
CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
|
CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
|
||||||
CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
|
CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
|
||||||
|
CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%", // SAFE_CHARS_URI
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string SanitizeString(const std::string& str, int rule)
|
std::string SanitizeString(const std::string& str, int rule)
|
||||||
|
|
|
@ -25,6 +25,7 @@ enum SafeChars
|
||||||
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
|
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
|
||||||
SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
|
SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
|
||||||
SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
|
SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
|
||||||
|
SAFE_CHARS_URI, //!< Chars allowed in URIs (RFC 3986)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -80,9 +80,9 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
||||||
block2.vtx.append(tx2)
|
block2.vtx.append(tx2)
|
||||||
assert_equal(block2.hashMerkleRoot, block2.calc_merkle_root())
|
assert_equal(block2.hashMerkleRoot, block2.calc_merkle_root())
|
||||||
assert_equal(orig_hash, block2.rehash())
|
assert_equal(orig_hash, block2.rehash())
|
||||||
assert(block2_orig.vtx != block2.vtx)
|
assert block2_orig.vtx != block2.vtx
|
||||||
|
|
||||||
node.p2p.send_blocks_and_test([block2], node, success=False, request_block=False, reject_code=16, reject_reason=b'bad-txns-duplicate')
|
node.p2p.send_blocks_and_test([block2], node, success=False, reject_code=16, reject_reason=b'bad-txns-duplicate')
|
||||||
|
|
||||||
# Check transactions for duplicate inputs
|
# Check transactions for duplicate inputs
|
||||||
self.log.info("Test duplicate input block.")
|
self.log.info("Test duplicate input block.")
|
||||||
|
@ -92,7 +92,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
||||||
block2_orig.hashMerkleRoot = block2_orig.calc_merkle_root()
|
block2_orig.hashMerkleRoot = block2_orig.calc_merkle_root()
|
||||||
block2_orig.rehash()
|
block2_orig.rehash()
|
||||||
block2_orig.solve()
|
block2_orig.solve()
|
||||||
node.p2p.send_blocks_and_test([block2_orig], node, success=False, request_block=False, reject_reason=b'bad-txns-inputs-duplicate')
|
node.p2p.send_blocks_and_test([block2_orig], node, success=False, reject_reason=b'bad-txns-inputs-duplicate')
|
||||||
|
|
||||||
self.log.info("Test very broken block.")
|
self.log.info("Test very broken block.")
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
||||||
block3.rehash()
|
block3.rehash()
|
||||||
block3.solve()
|
block3.solve()
|
||||||
|
|
||||||
node.p2p.send_blocks_and_test([block3], node, success=False, request_block=False, reject_code=16, reject_reason=b'bad-cb-amount')
|
node.p2p.send_blocks_and_test([block3], node, success=False, reject_code=16, reject_reason=b'bad-cb-amount')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
InvalidBlockRequestTest().main()
|
InvalidBlockRequestTest().main()
|
||||||
|
|
Loading…
Reference in a new issue