From 3088f83d016e7ebb6e6aa559e6326fa0ef0d6282 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Fri, 5 Mar 2021 14:50:49 +0100 Subject: [PATCH] fuzz: extend FuzzedSock::Recv() to support MSG_PEEK A conforming `recv(2)` call is supposed to return the same data on a call following `recv(..., MSG_PEEK)`. Extend `FuzzedSock::Recv()` to do that. For simplicity we only return 1 byte when `MSG_PEEK` is used. If we would return a buffer of N bytes, then we would have to keep track how many of them were consumed on subsequent non-`MSG_PEEK` calls. --- src/test/fuzz/util.h | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index 818246f73f..4f44394d2b 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -555,6 +555,13 @@ class FuzzedSock : public Sock { FuzzedDataProvider& m_fuzzed_data_provider; + /** + * Data to return when `MSG_PEEK` is used as a `Recv()` flag. + * If `MSG_PEEK` is used, then our `Recv()` returns some random data as usual, but on the next + * `Recv()` call we must return the same data, thus we remember it here. + */ + mutable std::optional m_peek_data; + public: explicit FuzzedSock(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider{fuzzed_data_provider} { @@ -635,8 +642,26 @@ public: } return r; } - const std::vector random_bytes = m_fuzzed_data_provider.ConsumeBytes( - m_fuzzed_data_provider.ConsumeIntegralInRange(0, len)); + std::vector random_bytes; + bool pad_to_len_bytes{m_fuzzed_data_provider.ConsumeBool()}; + if (m_peek_data.has_value()) { + // `MSG_PEEK` was used in the preceding `Recv()` call, return `m_peek_data`. + random_bytes.assign({m_peek_data.value()}); + if ((flags & MSG_PEEK) == 0) { + m_peek_data.reset(); + } + pad_to_len_bytes = false; + } else if ((flags & MSG_PEEK) != 0) { + // New call with `MSG_PEEK`. + random_bytes = m_fuzzed_data_provider.ConsumeBytes(1); + if (!random_bytes.empty()) { + m_peek_data = random_bytes[0]; + pad_to_len_bytes = false; + } + } else { + random_bytes = m_fuzzed_data_provider.ConsumeBytes( + m_fuzzed_data_provider.ConsumeIntegralInRange(0, len)); + } if (random_bytes.empty()) { const ssize_t r = m_fuzzed_data_provider.ConsumeBool() ? 0 : -1; if (r == -1) { @@ -645,7 +670,7 @@ public: return r; } std::memcpy(buf, random_bytes.data(), random_bytes.size()); - if (m_fuzzed_data_provider.ConsumeBool()) { + if (pad_to_len_bytes) { if (len > random_bytes.size()) { std::memset((char*)buf + random_bytes.size(), 0, len - random_bytes.size()); }