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:
MarcoFalke 2018-11-30 10:38:40 -05:00
commit d8bc0ce1da
No known key found for this signature in database
GPG key ID: D2EA4850E7528B25
10 changed files with 59 additions and 10 deletions

View file

@ -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>

View file

@ -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;

View file

@ -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)

View file

@ -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();

View file

@ -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"} },

View file

@ -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) {

View file

@ -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()

View file

@ -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)

View file

@ -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)
}; };
/** /**

View file

@ -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()