@@ -182,54 +182,54 @@ ssize_t FuzzedSock::Recv(void* buf, size_t len, int flags) const
182
182
EWOULDBLOCK,
183
183
};
184
184
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
+
185
191
if (len == 0 || m_fuzzed_data_provider.ConsumeBool ()) {
186
192
const ssize_t r = m_fuzzed_data_provider.ConsumeBool () ? 0 : -1 ;
187
193
if (r == -1 ) {
188
194
SetFuzzedErrNo (m_fuzzed_data_provider, recv_errnos);
189
195
}
190
196
return r;
191
197
}
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
+
194
201
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;
197
206
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 );
199
208
}
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);
210
209
}
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;
217
213
}
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 ());
228
223
}
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;
231
227
}
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;
233
233
}
234
234
235
235
int FuzzedSock::Connect (const sockaddr*, socklen_t ) const
0 commit comments