@@ -182,54 +182,54 @@ ssize_t FuzzedSock::Recv(void* buf, size_t len, int flags) const
182182 EWOULDBLOCK,
183183 };
184184 assert (buf != nullptr || len == 0 );
185+
186+ // Do the latency before any of the "return" statements.
187+ if (m_fuzzed_data_provider.ConsumeBool () && std::getenv (" FUZZED_SOCKET_FAKE_LATENCY" ) != nullptr ) {
188+ std::this_thread::sleep_for (std::chrono::milliseconds{2 });
189+ }
190+
185191 if (len == 0 || m_fuzzed_data_provider.ConsumeBool ()) {
186192 const ssize_t r = m_fuzzed_data_provider.ConsumeBool () ? 0 : -1 ;
187193 if (r == -1 ) {
188194 SetFuzzedErrNo (m_fuzzed_data_provider, recv_errnos);
189195 }
190196 return r;
191197 }
192- std::vector<uint8_t > random_bytes;
193- bool pad_to_len_bytes{m_fuzzed_data_provider.ConsumeBool ()};
198+
199+ size_t copied_so_far{0 };
200+
194201 if (!m_peek_data.empty ()) {
195- // `MSG_PEEK` was used in the preceding `Recv()` call, return `m_peek_data`.
196- random_bytes = m_peek_data;
202+ // `MSG_PEEK` was used in the preceding `Recv()` call, copy the first bytes from `m_peek_data`.
203+ const size_t copy_len{std::min (len, m_peek_data.size ())};
204+ std::memcpy (buf, m_peek_data.data (), copy_len);
205+ copied_so_far += copy_len;
197206 if ((flags & MSG_PEEK) == 0 ) {
198- m_peek_data.clear ( );
207+ m_peek_data.erase (m_peek_data. begin (), m_peek_data. begin () + copy_len );
199208 }
200- pad_to_len_bytes = false ;
201- } else if ((flags & MSG_PEEK) != 0 ) {
202- // New call with `MSG_PEEK`.
203- random_bytes = ConsumeRandomLengthByteVector (m_fuzzed_data_provider, len);
204- if (!random_bytes.empty ()) {
205- m_peek_data = random_bytes;
206- pad_to_len_bytes = false ;
207- }
208- } else {
209- random_bytes = ConsumeRandomLengthByteVector (m_fuzzed_data_provider, len);
210209 }
211- if (random_bytes.empty ()) {
212- const ssize_t r = m_fuzzed_data_provider.ConsumeBool () ? 0 : -1 ;
213- if (r == -1 ) {
214- SetFuzzedErrNo (m_fuzzed_data_provider, recv_errnos);
215- }
216- return r;
210+
211+ if (copied_so_far == len) {
212+ return copied_so_far;
217213 }
218- // `random_bytes` might exceed the size of `buf` if e.g. Recv is called with
219- // len=N and MSG_PEEK first and afterwards called with len=M (M < N) and
220- // without MSG_PEEK.
221- size_t recv_len{std::min (random_bytes.size (), len)};
222- std::memcpy (buf, random_bytes.data (), recv_len);
223- if (pad_to_len_bytes) {
224- if (len > random_bytes.size ()) {
225- std::memset ((char *)buf + random_bytes.size (), 0 , len - random_bytes.size ());
226- }
227- return len;
214+
215+ auto new_data = ConsumeRandomLengthByteVector (m_fuzzed_data_provider, len - copied_so_far);
216+ if (new_data.empty ()) return copied_so_far;
217+
218+ std::memcpy (reinterpret_cast <uint8_t *>(buf) + copied_so_far, new_data.data (), new_data.size ());
219+ copied_so_far += new_data.size ();
220+
221+ if ((flags & MSG_PEEK) != 0 ) {
222+ m_peek_data.insert (m_peek_data.end (), new_data.begin (), new_data.end ());
228223 }
229- if (m_fuzzed_data_provider.ConsumeBool () && std::getenv (" FUZZED_SOCKET_FAKE_LATENCY" ) != nullptr ) {
230- std::this_thread::sleep_for (std::chrono::milliseconds{2 });
224+
225+ if (copied_so_far == len || m_fuzzed_data_provider.ConsumeBool ()) {
226+ return copied_so_far;
231227 }
232- return recv_len;
228+
229+ // Pad to len bytes.
230+ std::memset (reinterpret_cast <uint8_t *>(buf) + copied_so_far, 0x0 , len - copied_so_far);
231+
232+ return len;
233233}
234234
235235int FuzzedSock::Connect (const sockaddr*, socklen_t ) const
0 commit comments