Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge #10408, #13291, and partial #13163
Summary: Merge #10408: Net: Improvements to Tor control port parser 49a199b torcontrol: Handle escapes in Tor QuotedStrings (Jack Grigg) 0182a11 torcontrol: Log invalid parameters in Tor reply strings where meaningful (Jack Grigg) 0b6f40d torcontrol: Check for reading errors in ReadBinaryFile (Jack Grigg) d63677b torcontrol: Fix ParseTorReplyMapping (Jack Grigg) 29f3c20 torcontrol: Add unit tests for Tor reply parsers (Jack Grigg) d8e03c0 torcontrol: Improve comments (Jack Grigg) Tree-SHA512: aa3ce8072d20299b38c4ba9471af7fab1f5df096c237bf40a96ee9274a357f7366f95ced0cc80f8da1f22f6455a1a8e68bad9a5ff71817eef3397b6aefcbc7ae Backport of Core PR10408 https://github.com/bitcoin/bitcoin/pull/10408/files Merge #13291: test: Don't include torcontrol.cpp into the test file 97c112d Declare TorReply parsing functions in torcontrol_tests (Ben Woosley) Pull request description: These methods are standalone string parsing methods which were included into test via an include of torcontrol.cpp, which is bad practice. ~~Splitting them out reveals that they were the only torcontrol.cpp methods under test, so the test file is renamed tor_reply_tests.cpp.~~ Introduced in #10408 Tree-SHA512: 8ff11a9c900a88f910a73dfe16f43581a567e9d60e9298a8a963fc9dd7cffb4d97a644da677610aafb7d89f1dd1cede9afeae2c6344305e021a9a322dbcea0ac Backport of Core PR13291 bitcoin/bitcoin#13291 (partial) Merge #13163: Make it clear which functions that are intended to be translation unit local c3f34d0 Make it clear which functions that are intended to be translation unit local (practicalswift) Pull request description: Make it clear which functions that are intended to be translation unit local. Do not share functions that are meant to be translation unit local with other translation units. Use internal linkage for those consistently. Tree-SHA512: 05eebd233d5cfbf6116724eec3a99b465bf534ca220f2b6f5e56341a7da41387454d3cb6ceadd8ab6714a5df94069e4ad0dcab8801ccc7e8949be7199a19fb53 Backport of Core PR13163 bitcoin/bitcoin#13163 Completes T612 Introduces a memory leak fixed by PR10587 bitcoin/bitcoin#10587 Memory leak fix: https://reviews.bitcoinabc.org/D3285 Includes a fix to the locale linter discussed with fabien D3285 should be landed immediately after this one Test Plan: make check test_runner.py sudo apt install tor # if not already installed sudo etc/init.d/tor status # to check if tor is running sudo etc/init.d/tor start # if it is not already running ./src/bitcoind -proxy=127.0.0.1:<tor port> ./bitcoin-cli getpeerinfo tor defaults to port 9050. `getpeerinfo` should be populated. arc lint should pass with no errors. Reviewers: jasonbcox, deadalnix, Fabien, O1 Bitcoin ABC, #bitcoin_abc Reviewed By: jasonbcox, deadalnix, Fabien, O1 Bitcoin ABC, #bitcoin_abc Differential Revision: https://reviews.bitcoinabc.org/D3283
- Loading branch information
Showing
5 changed files
with
294 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
// Copyright (c) 2017 The Zcash developers | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
// | ||
#include <torcontrol.h> | ||
|
||
#include <test/test_bitcoin.h> | ||
|
||
#include <boost/test/unit_test.hpp> | ||
|
||
#include <map> | ||
#include <string> | ||
#include <utility> | ||
|
||
std::pair<std::string, std::string> SplitTorReplyLine(const std::string &s); | ||
std::map<std::string, std::string> ParseTorReplyMapping(const std::string &s); | ||
|
||
BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup) | ||
|
||
static void CheckSplitTorReplyLine(std::string input, std::string command, | ||
std::string args) { | ||
BOOST_TEST_MESSAGE(std::string("CheckSplitTorReplyLine(") + input + ")"); | ||
auto ret = SplitTorReplyLine(input); | ||
BOOST_CHECK_EQUAL(ret.first, command); | ||
BOOST_CHECK_EQUAL(ret.second, args); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine) { | ||
// Data we should receive during normal usage | ||
CheckSplitTorReplyLine("PROTOCOLINFO PIVERSION", "PROTOCOLINFO", | ||
"PIVERSION"); | ||
CheckSplitTorReplyLine("AUTH METHODS=COOKIE,SAFECOOKIE " | ||
"COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"", | ||
"AUTH", | ||
"METHODS=COOKIE,SAFECOOKIE " | ||
"COOKIEFILE=\"/home/x/.tor/control_auth_cookie\""); | ||
CheckSplitTorReplyLine("AUTH METHODS=NULL", "AUTH", "METHODS=NULL"); | ||
CheckSplitTorReplyLine("AUTH METHODS=HASHEDPASSWORD", "AUTH", | ||
"METHODS=HASHEDPASSWORD"); | ||
CheckSplitTorReplyLine("VERSION Tor=\"0.2.9.8 (git-a0df013ea241b026)\"", | ||
"VERSION", "Tor=\"0.2.9.8 (git-a0df013ea241b026)\""); | ||
CheckSplitTorReplyLine("AUTHCHALLENGE SERVERHASH=aaaa SERVERNONCE=bbbb", | ||
"AUTHCHALLENGE", "SERVERHASH=aaaa SERVERNONCE=bbbb"); | ||
|
||
// Other valid inputs | ||
CheckSplitTorReplyLine("COMMAND", "COMMAND", ""); | ||
CheckSplitTorReplyLine("COMMAND SOME ARGS", "COMMAND", "SOME ARGS"); | ||
|
||
// These inputs are valid because PROTOCOLINFO accepts an OtherLine that is | ||
// just an OptArguments, which enables multiple spaces to be present | ||
// between the command and arguments. | ||
CheckSplitTorReplyLine("COMMAND ARGS", "COMMAND", " ARGS"); | ||
CheckSplitTorReplyLine("COMMAND EVEN+more ARGS", "COMMAND", | ||
" EVEN+more ARGS"); | ||
} | ||
|
||
static void | ||
CheckParseTorReplyMapping(std::string input, | ||
std::map<std::string, std::string> expected) { | ||
BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(") + input + ")"); | ||
auto ret = ParseTorReplyMapping(input); | ||
BOOST_CHECK_EQUAL(ret.size(), expected.size()); | ||
auto r_it = ret.begin(); | ||
auto e_it = expected.begin(); | ||
while (r_it != ret.end() && e_it != expected.end()) { | ||
BOOST_CHECK_EQUAL(r_it->first, e_it->first); | ||
BOOST_CHECK_EQUAL(r_it->second, e_it->second); | ||
r_it++; | ||
e_it++; | ||
} | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping) { | ||
// Data we should receive during normal usage | ||
CheckParseTorReplyMapping( | ||
"METHODS=COOKIE,SAFECOOKIE " | ||
"COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"", | ||
{ | ||
{"METHODS", "COOKIE,SAFECOOKIE"}, | ||
{"COOKIEFILE", "/home/x/.tor/control_auth_cookie"}, | ||
}); | ||
CheckParseTorReplyMapping("METHODS=NULL", { | ||
{"METHODS", "NULL"}, | ||
}); | ||
CheckParseTorReplyMapping("METHODS=HASHEDPASSWORD", | ||
{ | ||
{"METHODS", "HASHEDPASSWORD"}, | ||
}); | ||
CheckParseTorReplyMapping("Tor=\"0.2.9.8 (git-a0df013ea241b026)\"", | ||
{ | ||
{"Tor", "0.2.9.8 (git-a0df013ea241b026)"}, | ||
}); | ||
CheckParseTorReplyMapping("SERVERHASH=aaaa SERVERNONCE=bbbb", | ||
{ | ||
{"SERVERHASH", "aaaa"}, | ||
{"SERVERNONCE", "bbbb"}, | ||
}); | ||
CheckParseTorReplyMapping("ServiceID=exampleonion1234", | ||
{ | ||
{"ServiceID", "exampleonion1234"}, | ||
}); | ||
CheckParseTorReplyMapping("PrivateKey=RSA1024:BLOB", | ||
{ | ||
{"PrivateKey", "RSA1024:BLOB"}, | ||
}); | ||
CheckParseTorReplyMapping("ClientAuth=bob:BLOB", | ||
{ | ||
{"ClientAuth", "bob:BLOB"}, | ||
}); | ||
|
||
// Other valid inputs | ||
CheckParseTorReplyMapping("Foo=Bar=Baz Spam=Eggs", { | ||
{"Foo", "Bar=Baz"}, | ||
{"Spam", "Eggs"}, | ||
}); | ||
CheckParseTorReplyMapping("Foo=\"Bar=Baz\"", { | ||
{"Foo", "Bar=Baz"}, | ||
}); | ||
CheckParseTorReplyMapping("Foo=\"Bar Baz\"", { | ||
{"Foo", "Bar Baz"}, | ||
}); | ||
|
||
// Escapes | ||
CheckParseTorReplyMapping("Foo=\"Bar\\ Baz\"", { | ||
{"Foo", "Bar Baz"}, | ||
}); | ||
CheckParseTorReplyMapping("Foo=\"Bar\\Baz\"", { | ||
{"Foo", "BarBaz"}, | ||
}); | ||
CheckParseTorReplyMapping("Foo=\"Bar\\@Baz\"", { | ||
{"Foo", "Bar@Baz"}, | ||
}); | ||
CheckParseTorReplyMapping("Foo=\"Bar\\\"Baz\" Spam=\"\\\"Eggs\\\"\"", | ||
{ | ||
{"Foo", "Bar\"Baz"}, | ||
{"Spam", "\"Eggs\""}, | ||
}); | ||
CheckParseTorReplyMapping("Foo=\"Bar\\\\Baz\"", { | ||
{"Foo", "Bar\\Baz"}, | ||
}); | ||
|
||
// C escapes | ||
CheckParseTorReplyMapping( | ||
"Foo=\"Bar\\nBaz\\t\" Spam=\"\\rEggs\" " | ||
"Octals=\"\\1a\\11\\17\\18\\81\\377\\378\\400\\2222\" Final=Check", | ||
{ | ||
{"Foo", "Bar\nBaz\t"}, | ||
{"Spam", "\rEggs"}, | ||
{"Octals", "\1a\11\17\1" | ||
"881\377\37" | ||
"8\40" | ||
"0\222" | ||
"2"}, | ||
{"Final", "Check"}, | ||
}); | ||
CheckParseTorReplyMapping("Valid=Mapping Escaped=\"Escape\\\\\"", | ||
{ | ||
{"Valid", "Mapping"}, | ||
{"Escaped", "Escape\\"}, | ||
}); | ||
CheckParseTorReplyMapping("Valid=Mapping Bare=\"Escape\\\"", {}); | ||
CheckParseTorReplyMapping("OneOctal=\"OneEnd\\1\" TwoOctal=\"TwoEnd\\11\"", | ||
{ | ||
{"OneOctal", "OneEnd\1"}, | ||
{"TwoOctal", "TwoEnd\11"}, | ||
}); | ||
|
||
// Special handling for null case | ||
// (needed because string comparison reads the null as end-of-string) | ||
BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(Null=\"\\0\")")); | ||
auto ret = ParseTorReplyMapping("Null=\"\\0\""); | ||
BOOST_CHECK_EQUAL(ret.size(), 1); | ||
auto r_it = ret.begin(); | ||
BOOST_CHECK_EQUAL(r_it->first, "Null"); | ||
BOOST_CHECK_EQUAL(r_it->second.size(), 1); | ||
BOOST_CHECK_EQUAL(r_it->second[0], '\0'); | ||
|
||
// A more complex valid grammar. PROTOCOLINFO accepts a VersionLine that | ||
// takes a key=value pair followed by an OptArguments, making this valid. | ||
// Because an OptArguments contains no semantic data, there is no point in | ||
// parsing it. | ||
CheckParseTorReplyMapping("SOME=args,here MORE optional=arguments here", | ||
{ | ||
{"SOME", "args,here"}, | ||
}); | ||
|
||
// Inputs that are effectively invalid under the target grammar. | ||
// PROTOCOLINFO accepts an OtherLine that is just an OptArguments, which | ||
// would make these inputs valid. However, | ||
// - This parser is never used in that situation, because the | ||
// SplitTorReplyLine parser enables OtherLine to be skipped. | ||
// - Even if these were valid, an OptArguments contains no semantic data, | ||
// so there is no point in parsing it. | ||
CheckParseTorReplyMapping("ARGS", {}); | ||
CheckParseTorReplyMapping("MORE ARGS", {}); | ||
CheckParseTorReplyMapping("MORE ARGS", {}); | ||
CheckParseTorReplyMapping("EVEN more=ARGS", {}); | ||
CheckParseTorReplyMapping("EVEN+more ARGS", {}); | ||
} | ||
|
||
BOOST_AUTO_TEST_SUITE_END() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters