LCOV - code coverage report
Current view: top level - src/test - net_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 426 430 99.1 %
Date: 2025-02-23 09:33:43 Functions: 33 33 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2012-2016 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include "addrman.h"
       6             : #include "chainparams.h"
       7             : #include "hash.h"
       8             : #include "net.h"
       9             : #include "netbase.h"
      10             : #include "serialize.h"
      11             : #include "span.h"
      12             : #include "streams.h"
      13             : #include "version.h"
      14             : 
      15             : #include <cstdint>
      16             : 
      17             : #include "test/test_pivx.h"
      18             : 
      19             : #include <ios>
      20             : #include <string>
      21             : 
      22             : #include <boost/test/unit_test.hpp>
      23             : 
      24           4 : class CAddrManSerializationMock : public CAddrMan
      25             : {
      26             : public:
      27             :     virtual void Serialize(CDataStream::CBaseDataStream& s) const = 0;
      28             : 
      29             :     //! Ensure that bucket placement is always the same for testing purposes.
      30           2 :     void MakeDeterministic()
      31             :     {
      32           2 :         nKey.SetNull();
      33           2 :         SeedInsecureRand(SeedRand::ZEROS);
      34           2 :     }
      35             : };
      36             : 
      37           0 : class CAddrManUncorrupted : public CAddrManSerializationMock
      38             : {
      39             : public:
      40           2 :     void Serialize(CDataStream::CBaseDataStream& s) const
      41             :     {
      42           2 :         CAddrMan::Serialize(s);
      43           2 :     }
      44             : };
      45             : 
      46           0 : class CAddrManCorrupted : public CAddrManSerializationMock
      47             : {
      48             : public:
      49           2 :     void Serialize(CDataStream::CBaseDataStream& s) const
      50             :     {
      51             :         // Produces corrupt output that claims addrman has 20 addrs when it only has one addr.
      52           2 :         unsigned char nVersion = 1;
      53           2 :         s << nVersion;
      54           2 :         s << ((unsigned char)32);
      55           2 :         s << nKey;
      56           2 :         s << 10; // nNew
      57           2 :         s << 10; // nTried
      58             : 
      59           2 :         int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
      60           2 :         s << nUBuckets;
      61             : 
      62           2 :         CService serv;
      63           2 :         Lookup("252.1.1.1", serv, 7777, false);
      64           4 :         CAddress addr = CAddress(serv, NODE_NONE);
      65           4 :         CNetAddr resolved;
      66           2 :         LookupHost("252.2.2.2", resolved, false);
      67           4 :         CAddrInfo info = CAddrInfo(addr, resolved);
      68           2 :         s << info;
      69           2 :     }
      70             : };
      71             : 
      72           4 : CDataStream AddrmanToStream(CAddrManSerializationMock& addrman)
      73             : {
      74           4 :     CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
      75           4 :     ssPeersIn << Params().MessageStart();
      76           4 :     ssPeersIn << addrman;
      77           8 :     std::string str = ssPeersIn.str();
      78           8 :     std::vector<unsigned char> vchData(str.begin(), str.end());
      79           8 :     return CDataStream(vchData, SER_DISK, CLIENT_VERSION);
      80             : }
      81             : 
      82             : BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup)
      83             : 
      84           2 : BOOST_AUTO_TEST_CASE(cnode_listen_port)
      85             : {
      86             :     // test default
      87           1 :     uint16_t port = GetListenPort();
      88           2 :     BOOST_CHECK(port == Params().GetDefaultPort());
      89             :     // test set port
      90           1 :     uint16_t altPort = 12345;
      91           2 :     BOOST_CHECK(gArgs.SoftSetArg("-port", std::to_string(altPort)));
      92           1 :     port = GetListenPort();
      93           2 :     BOOST_CHECK(port == altPort);
      94           1 : }
      95             : 
      96           2 : BOOST_AUTO_TEST_CASE(caddrdb_read)
      97             : {
      98           1 :     CAddrManUncorrupted addrmanUncorrupted;
      99           1 :     addrmanUncorrupted.MakeDeterministic();
     100             : 
     101           2 :     CService addr1, addr2, addr3;
     102           2 :     BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
     103           2 :     BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false));
     104           2 :     BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false));
     105           3 :     BOOST_CHECK(Lookup(std::string("250.7.3.3", 9), addr3, 9999, false));
     106           4 :     BOOST_CHECK(!Lookup(std::string("250.7.3.3\0example.com", 21), addr3, 9999, false));
     107             : 
     108             :     // Add three addresses to new table.
     109           2 :     CService source;
     110           1 :     Lookup("252.5.1.1", source, 8333, false);
     111           2 :     addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source);
     112           2 :     addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source);
     113           2 :     addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source);
     114             : 
     115             :     // Test that the de-serialization does not throw an exception.
     116           2 :     CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
     117           1 :     bool exceptionThrown = false;
     118           2 :     CAddrMan addrman1;
     119             : 
     120           2 :     BOOST_CHECK(addrman1.size() == 0);
     121           1 :     try {
     122           1 :         unsigned char pchMsgTmp[4];
     123           1 :         ssPeers1 >> pchMsgTmp;
     124           1 :         ssPeers1 >> addrman1;
     125           0 :     } catch (const std::exception& e) {
     126           0 :         exceptionThrown = true;
     127             :     }
     128             : 
     129           2 :     BOOST_CHECK(addrman1.size() == 3);
     130           2 :     BOOST_CHECK(exceptionThrown == false);
     131             : 
     132             :     // Test that CAddrDB::Read creates an addrman with the correct number of addrs.
     133           2 :     CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted);
     134             : 
     135           2 :     CAddrMan addrman2;
     136           2 :     BOOST_CHECK(addrman2.size() == 0);
     137           2 :     BOOST_CHECK(CAddrDB::Read(addrman2, ssPeers2));
     138           2 :     BOOST_CHECK(addrman2.size() == 3);
     139           1 : }
     140             : 
     141             : 
     142           2 : BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
     143             : {
     144           1 :     CAddrManCorrupted addrmanCorrupted;
     145           1 :     addrmanCorrupted.MakeDeterministic();
     146             : 
     147             :     // Test that the de-serialization of corrupted addrman throws an exception.
     148           2 :     CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted);
     149           1 :     bool exceptionThrown = false;
     150           2 :     CAddrMan addrman1;
     151           2 :     BOOST_CHECK(addrman1.size() == 0);
     152           1 :     try {
     153           1 :         unsigned char pchMsgTmp[4];
     154           1 :         ssPeers1 >> pchMsgTmp;
     155           1 :         ssPeers1 >> addrman1;
     156           1 :     } catch (const std::exception& e) {
     157           1 :         exceptionThrown = true;
     158             :     }
     159             :     // Even through de-serialization failed addrman is not left in a clean state.
     160           2 :     BOOST_CHECK(addrman1.size() == 1);
     161           2 :     BOOST_CHECK(exceptionThrown);
     162             : 
     163             :     // Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails.
     164           2 :     CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted);
     165             : 
     166           2 :     CAddrMan addrman2;
     167           2 :     BOOST_CHECK(addrman2.size() == 0);
     168           2 :     BOOST_CHECK(!CAddrDB::Read(addrman2, ssPeers2));
     169           2 :     BOOST_CHECK(addrman2.size() == 0);
     170           1 : }
     171             : 
     172           2 : BOOST_AUTO_TEST_CASE(cnode_simple_test)
     173             : {
     174           1 :     SOCKET hSocket = INVALID_SOCKET;
     175           1 :     NodeId id = 0;
     176           1 :     int height = 0;
     177             : 
     178           1 :     in_addr ipv4Addr;
     179           1 :     ipv4Addr.s_addr = 0xa0b0c001;
     180             : 
     181           2 :     CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
     182           2 :     std::string pszDest = "";
     183           1 :     bool fInboundIn = false;
     184             : 
     185             :     // Test that fFeeler is false by default.
     186           2 :     std::unique_ptr<CNode> pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, pszDest, fInboundIn));
     187           2 :     BOOST_CHECK(pnode1->fInbound == false);
     188           2 :     BOOST_CHECK(pnode1->fFeeler == false);
     189             : 
     190           1 :     fInboundIn = true;
     191           2 :     std::unique_ptr<CNode> pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, pszDest, fInboundIn));
     192           2 :     BOOST_CHECK(pnode2->fInbound == true);
     193           2 :     BOOST_CHECK(pnode2->fFeeler == false);
     194           1 : }
     195             : 
     196           2 : BOOST_AUTO_TEST_CASE(cnetaddr_basic)
     197             : {
     198           1 :     CNetAddr addr;
     199             : 
     200             :     // IPv4, INADDR_ANY
     201           2 :     BOOST_REQUIRE(LookupHost("0.0.0.0", addr, false));
     202           2 :     BOOST_REQUIRE(!addr.IsValid());
     203           2 :     BOOST_REQUIRE(addr.IsIPv4());
     204             : 
     205           2 :     BOOST_CHECK(addr.IsBindAny());
     206           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     207           1 :     BOOST_CHECK_EQUAL(addr.ToString(), "0.0.0.0");
     208             : 
     209             :     // IPv4, INADDR_NONE
     210           2 :     BOOST_REQUIRE(LookupHost("255.255.255.255", addr, false));
     211           2 :     BOOST_REQUIRE(!addr.IsValid());
     212           2 :     BOOST_REQUIRE(addr.IsIPv4());
     213             : 
     214           2 :     BOOST_CHECK(!addr.IsBindAny());
     215           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     216           1 :     BOOST_CHECK_EQUAL(addr.ToString(), "255.255.255.255");
     217             : 
     218             :     // IPv4, casual
     219           2 :     BOOST_REQUIRE(LookupHost("12.34.56.78", addr, false));
     220           2 :     BOOST_REQUIRE(addr.IsValid());
     221           2 :     BOOST_REQUIRE(addr.IsIPv4());
     222             : 
     223           2 :     BOOST_CHECK(!addr.IsBindAny());
     224           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     225           1 :     BOOST_CHECK_EQUAL(addr.ToString(), "12.34.56.78");
     226             : 
     227             :     // IPv6, in6addr_any
     228           2 :     BOOST_REQUIRE(LookupHost("::", addr, false));
     229           2 :     BOOST_REQUIRE(!addr.IsValid());
     230           2 :     BOOST_REQUIRE(addr.IsIPv6());
     231             : 
     232           2 :     BOOST_CHECK(addr.IsBindAny());
     233           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     234           1 :     BOOST_CHECK_EQUAL(addr.ToString(), "::");
     235             : 
     236             :     // IPv6, casual
     237           3 :     BOOST_REQUIRE(LookupHost("1122:3344:5566:7788:9900:aabb:ccdd:eeff", addr, false));
     238           2 :     BOOST_REQUIRE(addr.IsValid());
     239           2 :     BOOST_REQUIRE(addr.IsIPv6());
     240             : 
     241           2 :     BOOST_CHECK(!addr.IsBindAny());
     242           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     243           2 :     BOOST_CHECK_EQUAL(addr.ToString(), "1122:3344:5566:7788:9900:aabb:ccdd:eeff");
     244             : 
     245             :     // TORv2
     246           3 :     BOOST_REQUIRE(addr.SetSpecial("6hzph5hv6337r6p2.onion"));
     247           2 :     BOOST_REQUIRE(addr.IsValid());
     248           2 :     BOOST_REQUIRE(addr.IsTor());
     249             : 
     250           2 :     BOOST_CHECK(!addr.IsBindAny());
     251           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     252           2 :     BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion");
     253             : 
     254             :     // TORv3
     255           1 :     const char* torv3_addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion";
     256           3 :     BOOST_REQUIRE(addr.SetSpecial(torv3_addr));
     257           2 :     BOOST_REQUIRE(addr.IsValid());
     258           2 :     BOOST_REQUIRE(addr.IsTor());
     259             : 
     260           2 :     BOOST_CHECK(!addr.IsBindAny());
     261           2 :     BOOST_CHECK(!addr.IsAddrV1Compatible());
     262           2 :     BOOST_CHECK_EQUAL(addr.ToString(), torv3_addr);
     263             : 
     264             :     // TORv3, broken, with wrong checksum
     265           3 :     BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscsad.onion"));
     266             : 
     267             :     // TORv3, broken, with wrong version
     268           3 :     BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscrye.onion"));
     269             : 
     270             :     // TORv3, malicious
     271           4 :     BOOST_CHECK(!addr.SetSpecial(std::string{
     272             :         "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd\0wtf.onion", 66}));
     273             : 
     274             :     // TOR, bogus length
     275           2 :     BOOST_CHECK(!addr.SetSpecial(std::string{"mfrggzak.onion"}));
     276             : 
     277             :     // TOR, invalid base32
     278           2 :     BOOST_CHECK(!addr.SetSpecial(std::string{"mf*g zak.onion"}));
     279             : 
     280             :     // Internal
     281           1 :     addr.SetInternal("esffpp");
     282           2 :     BOOST_REQUIRE(!addr.IsValid()); // "internal" is considered invalid
     283           2 :     BOOST_REQUIRE(addr.IsInternal());
     284             : 
     285           2 :     BOOST_CHECK(!addr.IsBindAny());
     286           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     287           2 :     BOOST_CHECK_EQUAL(addr.ToString(), "esffpvrt3wpeaygy.internal");
     288             : 
     289             :     // Totally bogus
     290           2 :     BOOST_CHECK(!addr.SetSpecial("totally bogus"));
     291           1 : }
     292             : 
     293           2 : BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v1)
     294             : {
     295           1 :     CNetAddr addr;
     296           2 :     CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
     297             : 
     298           1 :     s << addr;
     299           2 :     BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
     300           1 :     s.clear();
     301             : 
     302           2 :     BOOST_REQUIRE(LookupHost("1.2.3.4", addr, false));
     303           1 :     s << addr;
     304           2 :     BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000ffff01020304");
     305           1 :     s.clear();
     306             : 
     307           3 :     BOOST_REQUIRE(LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", addr, false));
     308           1 :     s << addr;
     309           2 :     BOOST_CHECK_EQUAL(HexStr(s), "1a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
     310           1 :     s.clear();
     311             : 
     312           3 :     BOOST_REQUIRE(addr.SetSpecial("6hzph5hv6337r6p2.onion"));
     313           1 :     s << addr;
     314           2 :     BOOST_CHECK_EQUAL(HexStr(s), "fd87d87eeb43f1f2f3f4f5f6f7f8f9fa");
     315           1 :     s.clear();
     316             : 
     317           3 :     BOOST_REQUIRE(addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));
     318           1 :     s << addr;
     319           2 :     BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
     320           1 :     s.clear();
     321             : 
     322           1 :     addr.SetInternal("a");
     323           1 :     s << addr;
     324           2 :     BOOST_CHECK_EQUAL(HexStr(s), "fd6b88c08724ca978112ca1bbdcafac2");
     325           2 :     s.clear();
     326           1 : }
     327             : 
     328           2 : BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v2)
     329             : {
     330           1 :     CNetAddr addr;
     331           2 :     CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
     332             :     // Add ADDRV2_FORMAT to the version so that the CNetAddr
     333             :     // serialize method produces an address in v2 format.
     334           1 :     s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
     335             : 
     336           1 :     s << addr;
     337           2 :     BOOST_CHECK_EQUAL(HexStr(s), "021000000000000000000000000000000000");
     338           1 :     s.clear();
     339             : 
     340           2 :     BOOST_REQUIRE(LookupHost("1.2.3.4", addr, false));
     341           1 :     s << addr;
     342           1 :     BOOST_CHECK_EQUAL(HexStr(s), "010401020304");
     343           1 :     s.clear();
     344             : 
     345           3 :     BOOST_REQUIRE(LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", addr, false));
     346           1 :     s << addr;
     347           2 :     BOOST_CHECK_EQUAL(HexStr(s), "02101a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
     348           1 :     s.clear();
     349             : 
     350           3 :     BOOST_REQUIRE(addr.SetSpecial("6hzph5hv6337r6p2.onion"));
     351           1 :     s << addr;
     352           2 :     BOOST_CHECK_EQUAL(HexStr(s), "030af1f2f3f4f5f6f7f8f9fa");
     353           1 :     s.clear();
     354             : 
     355           3 :     BOOST_REQUIRE(addr.SetSpecial("kpgvmscirrdqpekbqjsvw5teanhatztpp2gl6eee4zkowvwfxwenqaid.onion"));
     356           1 :     s << addr;
     357           2 :     BOOST_CHECK_EQUAL(HexStr(s), "042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88");
     358           1 :     s.clear();
     359             : 
     360           2 :     BOOST_REQUIRE(addr.SetInternal("a"));
     361           1 :     s << addr;
     362           2 :     BOOST_CHECK_EQUAL(HexStr(s), "0210fd6b88c08724ca978112ca1bbdcafac2");
     363           2 :     s.clear();
     364           1 : }
     365             : 
     366           2 : BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
     367             : {
     368           1 :     CNetAddr addr;
     369           2 :     CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
     370             :     // Add ADDRV2_FORMAT to the version so that the CNetAddr
     371             :     // unserialize method expects an address in v2 format.
     372           1 :     s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
     373             : 
     374             :     // Valid IPv4.
     375           1 :     s << MakeSpan(ParseHex("01"          // network type (IPv4)
     376             :                            "04"          // address length
     377           1 :                            "01020304")); // address
     378           1 :     s >> addr;
     379           2 :     BOOST_CHECK(addr.IsValid());
     380           2 :     BOOST_CHECK(addr.IsIPv4());
     381           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     382           1 :     BOOST_CHECK_EQUAL(addr.ToString(), "1.2.3.4");
     383           2 :     BOOST_REQUIRE(s.empty());
     384             : 
     385             :     // Invalid IPv4, valid length but address itself is shorter.
     386           1 :     s << MakeSpan(ParseHex("01"      // network type (IPv4)
     387             :                            "04"      // address length
     388           1 :                            "0102")); // address
     389           3 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure, HasReason("end of data"));
     390           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     391           1 :     s.clear();
     392             : 
     393             :     // Invalid IPv4, with bogus length.
     394           1 :     s << MakeSpan(ParseHex("01"          // network type (IPv4)
     395             :                            "05"          // address length
     396           1 :                            "01020304")); // address
     397           5 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
     398             :                           HasReason("BIP155 IPv4 address with length 5 (should be 4)"));
     399           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     400           1 :     s.clear();
     401             : 
     402             :     // Invalid IPv4, with extreme length.
     403           1 :     s << MakeSpan(ParseHex("01"          // network type (IPv4)
     404             :                            "fd0102"      // address length (513 as CompactSize)
     405           1 :                            "01020304")); // address
     406           5 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
     407             :                           HasReason("Address too long: 513 > 512"));
     408           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     409           1 :     s.clear();
     410             : 
     411             :     // Valid IPv6.
     412           1 :     s << MakeSpan(ParseHex("02"                                  // network type (IPv6)
     413             :                            "10"                                  // address length
     414           1 :                            "0102030405060708090a0b0c0d0e0f10")); // address
     415           1 :     s >> addr;
     416           2 :     BOOST_CHECK(addr.IsValid());
     417           2 :     BOOST_CHECK(addr.IsIPv6());
     418           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     419           2 :     BOOST_CHECK_EQUAL(addr.ToString(), "102:304:506:708:90a:b0c:d0e:f10");
     420           2 :     BOOST_REQUIRE(s.empty());
     421             : 
     422             :     // Valid IPv6, contains embedded "internal".
     423           1 :     s << MakeSpan(ParseHex(
     424             :         "02"                                  // network type (IPv6)
     425             :         "10"                                  // address length
     426           1 :         "fd6b88c08724ca978112ca1bbdcafac2")); // address: 0xfd + sha256("bitcoin")[0:5] +
     427             :                                               // sha256(name)[0:10]
     428           1 :     s >> addr;
     429           2 :     BOOST_CHECK(addr.IsInternal());
     430           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     431           2 :     BOOST_CHECK_EQUAL(addr.ToString(), "zklycewkdo64v6wc.internal");
     432           2 :     BOOST_REQUIRE(s.empty());
     433             : 
     434             :     // Invalid IPv6, with bogus length.
     435           1 :     s << MakeSpan(ParseHex("02"    // network type (IPv6)
     436             :                            "04"    // address length
     437           1 :                            "00")); // address
     438           5 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
     439             :                           HasReason("BIP155 IPv6 address with length 4 (should be 16)"));
     440           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     441           1 :     s.clear();
     442             : 
     443             :     // Invalid IPv6, contains embedded IPv4.
     444           1 :     s << MakeSpan(ParseHex("02"                                  // network type (IPv6)
     445             :                            "10"                                  // address length
     446           1 :                            "00000000000000000000ffff01020304")); // address
     447           1 :     s >> addr;
     448           2 :     BOOST_CHECK(!addr.IsValid());
     449           2 :     BOOST_REQUIRE(s.empty());
     450             : 
     451             :     // Invalid IPv6, contains embedded TORv2.
     452           1 :     s << MakeSpan(ParseHex("02"                                  // network type (IPv6)
     453             :                            "10"                                  // address length
     454           1 :                            "fd87d87eeb430102030405060708090a")); // address
     455           1 :     s >> addr;
     456           2 :     BOOST_CHECK(!addr.IsValid());
     457           2 :     BOOST_REQUIRE(s.empty());
     458             : 
     459             :     // Valid TORv2.
     460           1 :     s << MakeSpan(ParseHex("03"                      // network type (TORv2)
     461             :                            "0a"                      // address length
     462           1 :                            "f1f2f3f4f5f6f7f8f9fa")); // address
     463           1 :     s >> addr;
     464           2 :     BOOST_CHECK(addr.IsValid());
     465           2 :     BOOST_CHECK(addr.IsTor());
     466           2 :     BOOST_CHECK(addr.IsAddrV1Compatible());
     467           2 :     BOOST_CHECK_EQUAL(addr.ToString(), "6hzph5hv6337r6p2.onion");
     468           2 :     BOOST_REQUIRE(s.empty());
     469             : 
     470             :     // Invalid TORv2, with bogus length.
     471           1 :     s << MakeSpan(ParseHex("03"    // network type (TORv2)
     472             :                            "07"    // address length
     473           1 :                            "00")); // address
     474           5 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
     475             :                           HasReason("BIP155 TORv2 address with length 7 (should be 10)"));
     476           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     477           1 :     s.clear();
     478             : 
     479             :     // Valid TORv3.
     480           1 :     s << MakeSpan(ParseHex("04"                               // network type (TORv3)
     481             :                            "20"                               // address length
     482             :                            "79bcc625184b05194975c28b66b66b04" // address
     483             :                            "69f7f6556fb1ac3189a79b40dda32f1f"
     484           1 :                            ));
     485           1 :     s >> addr;
     486           2 :     BOOST_CHECK(addr.IsValid());
     487           2 :     BOOST_CHECK(addr.IsTor());
     488           2 :     BOOST_CHECK(!addr.IsAddrV1Compatible());
     489           2 :     BOOST_CHECK_EQUAL(addr.ToString(),
     490             :                       "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion");
     491           2 :     BOOST_REQUIRE(s.empty());
     492             : 
     493             :     // Invalid TORv3, with bogus length.
     494           1 :     s << MakeSpan(ParseHex("04" // network type (TORv3)
     495             :                            "00" // address length
     496             :                            "00" // address
     497           1 :                            ));
     498           5 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
     499             :                           HasReason("BIP155 TORv3 address with length 0 (should be 32)"));
     500           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     501           1 :     s.clear();
     502             : 
     503             :     // Valid I2P.
     504           1 :     s << MakeSpan(ParseHex("05"                               // network type (I2P)
     505             :                            "20"                               // address length
     506             :                            "a2894dabaec08c0051a481a6dac88b64" // address
     507           1 :                            "f98232ae42d4b6fd2fa81952dfe36a87"));
     508           1 :     s >> addr;
     509           2 :     BOOST_CHECK(addr.IsValid());
     510           2 :     BOOST_CHECK(addr.IsI2P());
     511           2 :     BOOST_CHECK(!addr.IsAddrV1Compatible());
     512           2 :     BOOST_CHECK_EQUAL(addr.ToString(),
     513             :                       "ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p");
     514           2 :     BOOST_REQUIRE(s.empty());
     515             : 
     516             :     // Invalid I2P, with bogus length.
     517           1 :     s << MakeSpan(ParseHex("05" // network type (I2P)
     518             :                            "03" // address length
     519             :                            "00" // address
     520           1 :                            ));
     521           5 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
     522             :                           HasReason("BIP155 I2P address with length 3 (should be 32)"));
     523           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     524           1 :     s.clear();
     525             : 
     526             :     // Valid CJDNS.
     527           1 :     s << MakeSpan(ParseHex("06"                               // network type (CJDNS)
     528             :                            "10"                               // address length
     529             :                            "fc000001000200030004000500060007" // address
     530           1 :                            ));
     531           1 :     s >> addr;
     532           2 :     BOOST_CHECK(addr.IsValid());
     533           2 :     BOOST_CHECK(addr.IsCJDNS());
     534           2 :     BOOST_CHECK(!addr.IsAddrV1Compatible());
     535           2 :     BOOST_CHECK_EQUAL(addr.ToString(), "fc00:1:2:3:4:5:6:7");
     536           2 :     BOOST_REQUIRE(s.empty());
     537             : 
     538             :     // Invalid CJDNS, with bogus length.
     539           1 :     s << MakeSpan(ParseHex("06" // network type (CJDNS)
     540             :                            "01" // address length
     541             :                            "00" // address
     542           1 :                            ));
     543           5 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
     544             :                           HasReason("BIP155 CJDNS address with length 1 (should be 16)"));
     545           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     546           1 :     s.clear();
     547             : 
     548             :     // Unknown, with extreme length.
     549           1 :     s << MakeSpan(ParseHex("aa"             // network type (unknown)
     550             :                            "fe00000002"     // address length (CompactSize's MAX_SIZE)
     551             :                            "01020304050607" // address
     552           1 :                            ));
     553           5 :     BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
     554             :                           HasReason("Address too long: 33554432 > 512"));
     555           2 :     BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
     556           1 :     s.clear();
     557             : 
     558             :     // Unknown, with reasonable length.
     559           1 :     s << MakeSpan(ParseHex("aa"       // network type (unknown)
     560             :                            "04"       // address length
     561             :                            "01020304" // address
     562           1 :                            ));
     563           1 :     s >> addr;
     564           2 :     BOOST_CHECK(!addr.IsValid());
     565           2 :     BOOST_REQUIRE(s.empty());
     566             : 
     567             :     // Unknown, with zero length.
     568           1 :     s << MakeSpan(ParseHex("aa" // network type (unknown)
     569             :                            "00" // address length
     570             :                            ""   // address
     571           1 :                            ));
     572           1 :     s >> addr;
     573           2 :     BOOST_CHECK(!addr.IsValid());
     574           2 :     BOOST_REQUIRE(s.empty());
     575           1 : }
     576             : 
     577             : // prior to PR #14728, this test triggers an undefined behavior
     578           2 : BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
     579             : {
     580             :     // set up local addresses; all that's necessary to reproduce the bug is
     581             :     // that a normal IPv4 address is among the entries, but if this address is
     582             :     // !IsRoutable the undefined behavior is easier to trigger deterministically
     583           1 :     {
     584           1 :         LOCK(cs_mapLocalHost);
     585           1 :         in_addr ipv4AddrLocal;
     586           1 :         ipv4AddrLocal.s_addr = 0x0100007f;
     587           2 :         CNetAddr addr = CNetAddr(ipv4AddrLocal);
     588           1 :         LocalServiceInfo lsi;
     589           1 :         lsi.nScore = 23;
     590           1 :         lsi.nPort = 42;
     591           1 :         mapLocalHost[addr] = lsi;
     592             :     }
     593             : 
     594             :     // create a peer with an IPv4 address
     595           1 :     in_addr ipv4AddrPeer;
     596           1 :     ipv4AddrPeer.s_addr = 0xa0b0c001;
     597           2 :     CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
     598           2 :     std::unique_ptr<CNode> pnode = std::make_unique<CNode>(0, NODE_NETWORK, 0, INVALID_SOCKET, addr, 0, 0, std::string{}, false);
     599           1 :     pnode->fSuccessfullyConnected.store(true);
     600             : 
     601             :     // the peer claims to be reaching us via IPv6
     602           1 :     in6_addr ipv6AddrLocal;
     603           1 :     memset(ipv6AddrLocal.s6_addr, 0, 16);
     604           1 :     ipv6AddrLocal.s6_addr[0] = 0xcc;
     605           3 :     CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK);
     606           1 :     pnode->SetAddrLocal(addrLocal);
     607             : 
     608             :     // before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
     609           1 :     AdvertiseLocal(&*pnode);
     610             : 
     611             :     // suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
     612           2 :     BOOST_CHECK(1);
     613           1 : }
     614             : 
     615             : 
     616           2 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
     617             : {
     618           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
     619           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
     620           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
     621             : 
     622           1 :     SetReachable(NET_IPV4, false);
     623           1 :     SetReachable(NET_IPV6, false);
     624           1 :     SetReachable(NET_ONION, false);
     625             : 
     626           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false);
     627           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false);
     628           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false);
     629             : 
     630           1 :     SetReachable(NET_IPV4, true);
     631           1 :     SetReachable(NET_IPV6, true);
     632           1 :     SetReachable(NET_ONION, true);
     633             : 
     634           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
     635           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
     636           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
     637           1 : }
     638             : 
     639           2 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
     640             : {
     641           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
     642           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
     643             : 
     644           1 :     SetReachable(NET_UNROUTABLE, false);
     645           1 :     SetReachable(NET_INTERNAL, false);
     646             : 
     647           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true); // Ignored for both networks
     648           1 :     BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
     649           1 : }
     650             : 
     651           2 : CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
     652             : {
     653           2 :     unsigned char ip[] = {p1, p2, p3, p4};
     654             : 
     655           2 :     struct sockaddr_in sa;
     656           2 :     memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
     657           2 :     memcpy(&(sa.sin_addr), &ip, sizeof(ip));
     658           2 :     return CNetAddr(sa.sin_addr);
     659             : }
     660             : 
     661             : 
     662           2 : BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
     663             : {
     664           1 :     CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
     665             : 
     666           1 :     SetReachable(NET_IPV4, true);
     667           1 :     BOOST_CHECK_EQUAL(IsReachable(addr), true);
     668             : 
     669           1 :     SetReachable(NET_IPV4, false);
     670           1 :     BOOST_CHECK_EQUAL(IsReachable(addr), false);
     671             : 
     672           1 :     SetReachable(NET_IPV4, true); // have to reset this, because this is stateful.
     673           1 : }
     674             : 
     675             : 
     676           2 : BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
     677             : {
     678           1 :     CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
     679             : 
     680           1 :     SetReachable(NET_IPV4, true);
     681             : 
     682           1 :     BOOST_CHECK_EQUAL(IsLocal(addr), false);
     683           1 :     BOOST_CHECK_EQUAL(AddLocal(addr, 1000), true);
     684           1 :     BOOST_CHECK_EQUAL(IsLocal(addr), true);
     685             : 
     686           1 :     RemoveLocal(addr);
     687           1 :     BOOST_CHECK_EQUAL(IsLocal(addr), false);
     688           1 : }
     689             : 
     690           2 : BOOST_AUTO_TEST_CASE(PoissonNextSend)
     691             : {
     692           1 :     g_mock_deterministic_tests = true;
     693             : 
     694           1 :     int64_t now = 5000;
     695           1 :     int average_interval_seconds = 600;
     696             : 
     697           1 :     auto poisson = ::PoissonNextSend(now, average_interval_seconds);
     698           1 :     std::chrono::microseconds poisson_chrono = ::PoissonNextSend(std::chrono::microseconds{now}, std::chrono::seconds{average_interval_seconds});
     699             : 
     700           1 :     BOOST_CHECK_EQUAL(poisson, poisson_chrono.count());
     701             : 
     702           1 :     g_mock_deterministic_tests = false;
     703           1 : }
     704             : 
     705             : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.14