@@ -189,4 +189,42 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
189189 BOOST_CHECK (pnode2->fFeeler == false );
190190}
191191
192+ // prior to PR #14728, this test triggers an undefined behavior
193+ BOOST_AUTO_TEST_CASE (ipv4_peer_with_ipv6_addrMe_test)
194+ {
195+ // set up local addresses; all that's necessary to reproduce the bug is
196+ // that a normal IPv4 address is among the entries, but if this address is
197+ // !IsRoutable the undefined behavior is easier to trigger deterministically
198+ {
199+ LOCK (cs_mapLocalHost);
200+ in_addr ipv4AddrLocal;
201+ ipv4AddrLocal.s_addr = 0x0100007f ;
202+ CNetAddr addr = CNetAddr (ipv4AddrLocal);
203+ LocalServiceInfo lsi;
204+ lsi.nScore = 23 ;
205+ lsi.nPort = 42 ;
206+ mapLocalHost[addr] = lsi;
207+ }
208+
209+ // create a peer with an IPv4 address
210+ in_addr ipv4AddrPeer;
211+ ipv4AddrPeer.s_addr = 0xa0b0c001 ;
212+ CAddress addr = CAddress (CService (ipv4AddrPeer, 7777 ), NODE_NETWORK);
213+ std::unique_ptr<CNode> pnode = MakeUnique<CNode>(0 , NODE_NETWORK, 0 , INVALID_SOCKET, addr, 0 , 0 , CAddress{}, std::string{}, false );
214+ pnode->fSuccessfullyConnected .store (true );
215+
216+ // the peer claims to be reaching us via IPv6
217+ in6_addr ipv6AddrLocal;
218+ memset (ipv6AddrLocal.s6_addr , 0 , 16 );
219+ ipv6AddrLocal.s6_addr [0 ] = 0xcc ;
220+ CAddress addrLocal = CAddress (CService (ipv6AddrLocal, 7777 ), NODE_NETWORK);
221+ pnode->SetAddrLocal (addrLocal);
222+
223+ // before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
224+ AdvertiseLocal (&*pnode);
225+
226+ // suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
227+ BOOST_CHECK (1 );
228+ }
229+
192230BOOST_AUTO_TEST_SUITE_END ()
0 commit comments