Skip to content

Commit 366e3e1

Browse files
fuzz: Add FUZZED_SOCKET_FAKE_LATENCY mode to FuzzedSock to allow for fuzzing timeout logic
1 parent b22d4c1 commit 366e3e1

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

src/netbase.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
3939
bool fNameLookup = DEFAULT_NAME_LOOKUP;
4040

4141
// Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
42-
static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
42+
int g_socks5_recv_timeout = 20 * 1000;
4343
static std::atomic<bool> interruptSocks5Recv(false);
4444

4545
enum Network ParseNetwork(const std::string& net_in) {
@@ -455,7 +455,7 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
455455
return error("Error sending to proxy");
456456
}
457457
uint8_t pchRet1[2];
458-
if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, sock)) != IntrRecvError::OK) {
458+
if ((recvr = InterruptibleRecv(pchRet1, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
459459
LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
460460
return false;
461461
}
@@ -478,7 +478,7 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
478478
}
479479
LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
480480
uint8_t pchRetA[2];
481-
if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, sock)) != IntrRecvError::OK) {
481+
if ((recvr = InterruptibleRecv(pchRetA, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
482482
return error("Error reading proxy authentication response");
483483
}
484484
if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
@@ -503,7 +503,7 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
503503
return error("Error sending to proxy");
504504
}
505505
uint8_t pchRet2[4];
506-
if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, sock)) != IntrRecvError::OK) {
506+
if ((recvr = InterruptibleRecv(pchRet2, 4, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
507507
if (recvr == IntrRecvError::Timeout) {
508508
/* If a timeout happens here, this effectively means we timed out while connecting
509509
* to the remote node. This is very common for Tor, so do not print an
@@ -527,24 +527,24 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
527527
uint8_t pchRet3[256];
528528
switch (pchRet2[3])
529529
{
530-
case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, sock); break;
531-
case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, sock); break;
530+
case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, g_socks5_recv_timeout, sock); break;
531+
case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, g_socks5_recv_timeout, sock); break;
532532
case SOCKS5Atyp::DOMAINNAME:
533533
{
534-
recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, sock);
534+
recvr = InterruptibleRecv(pchRet3, 1, g_socks5_recv_timeout, sock);
535535
if (recvr != IntrRecvError::OK) {
536536
return error("Error reading from proxy");
537537
}
538538
int nRecv = pchRet3[0];
539-
recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, sock);
539+
recvr = InterruptibleRecv(pchRet3, nRecv, g_socks5_recv_timeout, sock);
540540
break;
541541
}
542542
default: return error("Error: malformed proxy response");
543543
}
544544
if (recvr != IntrRecvError::OK) {
545545
return error("Error reading from proxy");
546546
}
547-
if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, sock)) != IntrRecvError::OK) {
547+
if ((recvr = InterruptibleRecv(pchRet3, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
548548
return error("Error reading from proxy");
549549
}
550550
LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);

src/test/fuzz/socks5.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@
1111
#include <string>
1212
#include <vector>
1313

14+
namespace {
15+
int default_socks5_recv_timeout;
16+
};
17+
18+
extern int g_socks5_recv_timeout;
19+
1420
void initialize_socks5()
1521
{
1622
static const auto testing_setup = MakeNoLogFileContext<const BasicTestingSetup>();
23+
default_socks5_recv_timeout = g_socks5_recv_timeout;
1724
}
1825

1926
FUZZ_TARGET_INIT(socks5, initialize_socks5)
@@ -23,6 +30,9 @@ FUZZ_TARGET_INIT(socks5, initialize_socks5)
2330
proxy_credentials.username = fuzzed_data_provider.ConsumeRandomLengthString(512);
2431
proxy_credentials.password = fuzzed_data_provider.ConsumeRandomLengthString(512);
2532
InterruptSocks5(fuzzed_data_provider.ConsumeBool());
33+
// Set FUZZED_SOCKET_FAKE_LATENCY=1 to exercise recv timeout code paths. This
34+
// will slow down fuzzing.
35+
g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1 : default_socks5_recv_timeout;
2636
FuzzedSock fuzzed_sock = ConsumeSock(fuzzed_data_provider);
2737
// This Socks5(...) fuzzing harness would have caught CVE-2017-18350 within
2838
// a few seconds of fuzzing.

src/test/fuzz/util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,9 @@ class FuzzedSock : public Sock
642642
}
643643
return len;
644644
}
645+
if (m_fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) {
646+
std::this_thread::sleep_for(std::chrono::milliseconds{2});
647+
}
645648
return random_bytes.size();
646649
}
647650

0 commit comments

Comments
 (0)