- split FuzzedSock interface and implementation
- make FuzzedSock::Wait() sometimes simulate an occurred event
- set errno from FuzzedSock::Wait() if it simulates a failure
(this is a followup from #21617)
Concept ACK
Thanks for making src/test/fuzz/ an even better place!
Can the uninitialized read also happen in i2p? (The Wait return code is ignored here):
src/i2p.cpp=bool Session::Accept(Connection& conn)
src/i2p.cpp-{
src/i2p.cpp- try {
src/i2p.cpp- while (!*m_interrupt) {
src/i2p.cpp- Sock::Event occurred;
src/i2p.cpp: conn.sock->Wait(MAX_WAIT_FOR_IO, Sock::RECV, &occurred);
src/i2p.cpp-
src/i2p.cpp- if ((occurred & Sock::RECV) == 0) {
review-only ACK d2e8d121eff98f9bbc3f15977bfb1dda9a27245a 📧
<details><summary>Show signature and timestamp</summary>
Signature:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
review-only ACK d2e8d121eff98f9bbc3f15977bfb1dda9a27245a 📧
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUg1aQv/aeRus5hrRnP5M5V3tAv4J17uP4l0h7ApjymlEHRgJvNLlBTDAjOKdji/
u3CYy9mEuxrLn1tv5TGqBMXy1YQLrj2x1R0ExBp96LRalfRPVyTpocx/yOhokfj0
sgy5MyPOpNg4WbcxMU6z0Mli2mg0TBg9pii/b5+KTQg7SdnSsjMXkWYoBYIBvcLk
g/Ra92zzNjYcUGYLM5zDbTu3oU/wbhV7M1H5xapm29heIhtJ3FfSGo5zlA5BynVO
nMNjq9+I04e3qpPopH0wnsSaApnqlFqzRdUNADTMdkyB+tqolDxet3G4GRR0SPGL
8TR7BXBUqAKNfx37x2+4hM5cUnTh+eByyemrRXlyMwAGWzo6QBmINbmD6dbPLT/t
KZUAiKPN7ppA0nsSBdmejAX37ZyVKLFjtC0Nd2XT6XNKXCaYA27lL7VNbQJ2wpOq
fayqkcxeAre8F+5rFq7/oIWSU8ArIXM9ruWhXO6OOFB0MHgcN23CgQ58jfvGLIoM
6nO8IrZq
=aNPu
-----END PGP SIGNATURE-----
Timestamp of file with hash fbf1a942dcb87778554e8487c05545ff298d95af1816d6f90d53986f457f41d2 -
</details>
177 | + constexpr std::array wait_errnos{ 178 | + EBADF, 179 | + EINTR, 180 | + EINVAL, 181 | + }; 182 | if (!m_fuzzed_data_provider.ConsumeBool()) {
If you want you can remove the !, now that you are breaking the input format anyway
Done.
Consider adding [[nodiscard]] to Wait: such an annotation would likely have saved us from the uninitialized read reported in #21617.
[[nodiscard]] is great for functions where an ignored return value is likely to be unintentional (like in this case!). I think we underuse [[nodiscard]] :)
review ACK 841905bb61e34faa97b34f4f0c97f7581092a988 🍰
<details><summary>Show signature and timestamp</summary>
Signature:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
review ACK 841905bb61e34faa97b34f4f0c97f7581092a988 🍰
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUhL0Av/boScIgVINXDYMJ262ndgfw3HxUyP9JYZLZ/LFDjDhnuLCoBYqfnGvs63
u8DZKbJoFtxjyHkasgOMgWindvj9ae/qzTNkLSBoT8Z6oWoooRhmjawvWXCj2OhO
TxfqVpY9FtcpnXMHZUWN3nx8qbGeAkhdoQ8dB3V0tCa1N+74taaLB1GmgcaJzy/8
Mftf7AymvV/lgWSvZjcIOv1JoXKqw2vEYEkDUoXJuVyiVeqZXzYPeT/ZAgFrlQed
ui3KjNa8RT/VGa4+rQee6rl76oSUcjBBRiAw+nRGpi4J3cxu15yHoD/ETR0OVow3
z0d//mhKHbn6Pyn4tqJ23ple4/JlFRgAuZBEBPYcfxVUYBfPNHgOiomoIKA5fLnK
ByJcIa0hHsPVMy54bzXHMrPyDaFeXw/563/lPsJt9IgJ3o73B3hQ0PGbtvmZe3FH
K4lSSuxOWBNdowECW0qMweSH36kzrB9KQPvF2ov+KGNbd5j8ErB8M5GtpLcMy4mq
RBX26q3v
=eXO6
-----END PGP SIGNATURE-----
Timestamp of file with hash 3f87a5b288e93fbd4eb780ede4aca90eea4b994dd7a1d9c2be7101c3fbf5173f -
</details>
@practicalswift, I will do [[nodiscard]] in a separate PR, once #21631 is merged.
6 | @@ -7,15 +7,196 @@ 7 | #include <util/rbf.h> 8 | #include <version.h> 9 | 10 | -bool FuzzedSock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred ) const 11 | +FuzzedSock::FuzzedSock(FuzzedDataProvider& fuzzed_data_provider) 12 | + : m_fuzzed_data_provider{fuzzed_data_provider} 13 | { 14 | - if (!m_fuzzed_data_provider.ConsumeBool()) { 15 | + m_socket = fuzzed_data_provider.ConsumeIntegral<SOCKET>();
Not changed in this PR, but is there any scenario where we want m_socket != INVALID_SOCKET here?
Otherwise I'd prefer going with INVALID_SOCKET. Perhaps Sock::m_socket could be default initialized to INVALID_SOCKET. That should be a safe default.
Normally we want the fuzzed socket's m_socket to be != INVALID_SOCKET, otherwise a code that does if (sock.Get() == INVALID_SOCKET) will "misbehave" when mocked.
@vasild Oh, I didn't think about the possibility to peek at m_socket via Get(). But then I guess we want two cases: 1.) m_socket == INVALID_SOCKET, and 2.) m_socket != INVALID_SOCKET where m_socket is a very high number which is unlikely to coincide with a real opened file descriptor?
The current code allows m_socket to be set to low numbers such as 0, 1, 2, 3, etc which may be problematic :)
Perhaps m_socket = fuzzed_data_provider.ConsumeIntegralInRange<SOCKET>(INVALID_SOCKET - 1, INVALID_SOCKET)?
Right! And we can do even better:
Sock object "owns" a socket, similar to std::unique_ptr::operator bool() so that callers don't do Get() == INVALID_SOCKET.getsockname(), setsockopt(), bind() and listen(). That way more code will be mockable, but more importantly - then nobody would need to call Sock::Get() anymore so the value of m_socket will remain "hidden" within the Sock class.@vasild Sounds good! Until we have that in place I think it makes sense to set m_socket to very high numbers here to avoid nasty surprises :) The thought of random reads/writes to existing open file descriptors is a bit scary even if only from fuzzing code.
Add wrapper methods for ...
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--174a7506f384e20aa4161008e828411d-->
No conflicts as of last run.
Move the `FuzzedSock`'s implementation from `src/test/fuzz/util.h` to
`src/test/fuzz/util.cpp`.
A separate interface and implementation make the code more readable for
consumers who don't need to (better not) know the implementation
details.
The former is shorter and ends up with a "random" bool anyway.
841905bb6...549c82ad3: rebase due to conflicts
cr ACK 549c82ad3a34a885ecca37a5f04c36dfbaa95d17: patch looks correct and touches only src/test/fuzz/
re-ACK 549c82ad3a34a885ecca37a5f04c36dfbaa95d17 only change is rebase 🎬
<details><summary>Show signature and timestamp</summary>
Signature:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
re-ACK 549c82ad3a34a885ecca37a5f04c36dfbaa95d17 only change is rebase 🎬
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUjNUwv5AZxj+qkRP+IARG87hMf1liImC+MpuCNqfr2qE2faCtn9+lGilUiSYIMo
Tmf4R06QIevh+jlAAbXazLwB7eLrSrFX25dIgQ7f6ijCMXEl8ezcic58WY1K7gF4
OhWm6bjDHYOH6b70fIpAHIXxsZViIJD1N1COqoD999rvFkTkCkREQXIsk1LkHxAJ
Cr45GFJ7zSo55WIxV8NSfvUFDftENjlgu0/YB4n6wraIaQ3sNiRe7n45eqVt5Zc2
Z0lnE3+9JwbCZKpsNcJ9C5G24KcIxyc/hbB5qwP+uF58b2ANGry5KJjMEyGJ5TWp
hWWxcjZQq1ZhaEoCOpapKKyTDPckTLfE4TfpJz5h3YbVzEXezT+nUskZoCHTc9b7
Oldfw9BF7foMyhS83QOfjDd4POw7rtPaWT7PR0lRAKbXGHjy9PYHpocXoLlvXJPz
asKm+tfedIyfIVO24aRPMnrW22KUFX9Hrd56lqeo21SVHXT22zyz+bcDyNSV8541
zTOdMYVQ
=0nmO
-----END PGP SIGNATURE-----
Timestamp of file with hash fefa9f6ff7ab6d5c5d493fb447f3ba78a5d161e01bf1afb703b033184420ad98 -
</details>