This is a piece of #21878, chopped off to ease review.
Add new methods Sock::Bind()
and Sock::Listen()
that wrap bind()
and listen()
.
This will help to increase Sock
usage and make more code mockable.
Concept ACK
I’m not too familiar on fuzzing and setting errno. May I ask what is the rationale for choosing the errno arrays in the fuzz tests? According to the linux manpages, there are some more possible errno vaues that bind
and listen
could set:
https://man7.org/linux/man-pages/man2/bind.2.html (EACCES, EADDRINUSE, EBADF, EINVAL, ENOTSOCK)
https://man7.org/linux/man-pages/man2/listen.2.html (EADDRINUSE, EBADF, ENOTSOCK, EOPNOTSUPP)
Note that there’s a typo in the PR title: s/mockatble/mockable/
what is the rationale for choosing the errno arrays in the fuzz tests?
Not much, other than the first one must be a permanent error in order to avoid infinite loops in case the app code decides to retry on EAGAIN
(for example) and the syscall keeps returning EAGAIN
forever:
I think it is good to have both temporary errors (e.g. EAGAIN
or EINTR
) and permanent ones because that may trigger different code paths:
https://github.com/bitcoin/bitcoin/blob/c9ed9927bbb7c422c4e01c0c1adc9722b8671009/src%2Fnet.cpp#L1677
I added the comments and EADDRINUSE
to Listen()
, thanks!
5249fc7b7f...c2f80ba98d
: add comments about errno arrays in fuzz-mocked bind()
and listen()
syscalls and also return EADDRINUSE
from Listen()
.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
This will help to increase `Sock` usage and make more code mockable.
This will help to increase `Sock` usage and make more code mockable.
159@@ -160,6 +160,41 @@ int FuzzedSock::Connect(const sockaddr*, socklen_t) const
160 return 0;
161 }
162
163+int FuzzedSock::Bind(const sockaddr*, socklen_t) const
164+{
165+ // Have a permanent error at bind_errnos[0] because when the fuzzed data is exhausted
166+ // SetFuzzedErrNo() will always return the first element and we want to avoid Bind()
167+ // returning -1 and setting errno to EAGAIN repeatedly.
This comment threw me off a little. Is this clearer to what is actually happening inside SetFuzzedEerrNo
?
0 // Have a permanent error at bind_errnos[0] because when the fuzzed data is exhausted
1 // SetFuzzedErrNo() will always set the first element. We want to avoid Bind()
2 // returning -1 and setting errno to EAGAIN repeatedly.
Hmm, I see where the confusion comes from - SetFuzzedErrNo()
does not return the value but rather sets the global variable errno
to it.
What about this:
0 // Have a permanent error at bind_errnos[0] because when the fuzzed data is exhausted
1 // SetFuzzedErrNo() will always set the global errno to bind_errnos[0]. We want to avoid Bind()
2 // returning -1 and setting errno to EAGAIN repeatedly because a legit code should retry on
3 // temporary errors leading to an infinite loop.
c2f80ba98d...b2733ab6a8
: improve wording in comments
2407@@ -2409,7 +2408,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
2408 LogPrintf("Bound to %s\n", addrBind.ToString());
2409
2410 // Listen for incoming connections
2411- if (listen(sock->Get(), SOMAXCONN) == SOCKET_ERROR)
2412+ if (sock->Listen(SOMAXCONN) == SOCKET_ERROR)
Approach ACK, light ACK
Should #include <sys/socket.h>
headers be added? (socklen_t
, etc.)
Should
#include <sys/socket.h>
headers be added? (socklen_t
, etc.)
You mean in sock.h
? I think “no” because including sys/socket.h
involves some #ifdef WIN32
magic and is only done in compat.h
which is included in sock.h
.