Avi Drissman | 6459548 | 2022-09-14 20:52:29 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
mmenke | 91c1716 | 2016-06-02 16:03:23 | [diff] [blame] | 5 | #ifndef NET_SOCKET_FUZZED_SOCKET_H_ |
| 6 | #define NET_SOCKET_FUZZED_SOCKET_H_ |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 7 | |
| 8 | #include <stdint.h> |
| 9 | |
Keishi Hattori | 98eca68 | 2023-03-31 03:10:09 | [diff] [blame] | 10 | #include "base/memory/raw_ptr.h" |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 11 | #include "base/memory/weak_ptr.h" |
Mario Sanchez Prada | 3f9c238 | 2019-04-03 22:31:14 | [diff] [blame] | 12 | #include "net/base/completion_once_callback.h" |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 13 | #include "net/base/ip_endpoint.h" |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 14 | #include "net/base/net_errors.h" |
mikecirone | f22f981 | 2016-10-04 03:40:19 | [diff] [blame] | 15 | #include "net/log/net_log_with_source.h" |
Helen Li | d5bb922 | 2018-04-12 15:33:09 | [diff] [blame] | 16 | #include "net/socket/transport_client_socket.h" |
[email protected] | a2b2cfc | 2017-12-06 09:06:08 | [diff] [blame] | 17 | #include "net/traffic_annotation/network_traffic_annotation.h" |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 18 | |
csharrison | f30fc95f | 2016-08-19 21:43:44 | [diff] [blame] | 19 | class FuzzedDataProvider; |
csharrison | f30fc95f | 2016-08-19 21:43:44 | [diff] [blame] | 20 | |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 21 | namespace net { |
| 22 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 23 | class IPEndPoint; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 24 | class IOBuffer; |
mikecirone | f22f981 | 2016-10-04 03:40:19 | [diff] [blame] | 25 | class NetLog; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 26 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 27 | // A StreamSocket that uses a FuzzedDataProvider to generate responses. Writes |
| 28 | // can succeed synchronously or asynchronously, can write some or all of the |
| 29 | // provided data, and can fail with several different errors. Reads can do the |
| 30 | // same, but the read data is also generated from the FuzzedDataProvider. The |
| 31 | // number of bytes written/read from a single call is currently capped at 255 |
| 32 | // bytes. |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 33 | // |
| 34 | // Reads and writes are executed independently of one another, so to guarantee |
| 35 | // the fuzzer behaves the same across repeated runs with the same input, the |
| 36 | // reads and writes must be done in a deterministic order and for a |
| 37 | // deterministic number of bytes, every time the fuzzer is run with the same |
| 38 | // data. |
Helen Li | d5bb922 | 2018-04-12 15:33:09 | [diff] [blame] | 39 | class FuzzedSocket : public TransportClientSocket { |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 40 | public: |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 41 | // |data_provider| is used as to determine behavior of the FuzzedSocket. It |
| 42 | // must remain valid until after the FuzzedSocket is destroyed. |
Max Moroz | cfbe47cc | 2019-06-24 17:45:02 | [diff] [blame] | 43 | FuzzedSocket(FuzzedDataProvider* data_provider, net::NetLog* net_log); |
Peter Boström | 293b134 | 2021-09-22 17:31:43 | [diff] [blame] | 44 | |
| 45 | FuzzedSocket(const FuzzedSocket&) = delete; |
| 46 | FuzzedSocket& operator=(const FuzzedSocket&) = delete; |
| 47 | |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 48 | ~FuzzedSocket() override; |
| 49 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 50 | // If set to true, the socket will fuzz the result of the Connect() call. |
| 51 | // It can fail or succeed, and return synchronously or asynchronously. If |
| 52 | // false, Connect() succeeds synchronously. Defaults to false. |
| 53 | void set_fuzz_connect_result(bool fuzz_connect_result) { |
| 54 | fuzz_connect_result_ = fuzz_connect_result; |
| 55 | } |
| 56 | |
| 57 | // Sets the remote address the socket claims to be using. |
| 58 | void set_remote_address(const IPEndPoint& remote_address) { |
| 59 | remote_address_ = remote_address; |
| 60 | } |
| 61 | |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 62 | // Socket implementation: |
| 63 | int Read(IOBuffer* buf, |
| 64 | int buf_len, |
Brad Lassey | 3a81417 | 2018-04-26 03:30:21 | [diff] [blame] | 65 | CompletionOnceCallback callback) override; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 66 | int Write(IOBuffer* buf, |
| 67 | int buf_len, |
Brad Lassey | 3a81417 | 2018-04-26 03:30:21 | [diff] [blame] | 68 | CompletionOnceCallback callback, |
[email protected] | 578968d4 | 2017-12-13 15:39:32 | [diff] [blame] | 69 | const NetworkTrafficAnnotationTag& traffic_annotation) override; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 70 | int SetReceiveBufferSize(int32_t size) override; |
| 71 | int SetSendBufferSize(int32_t size) override; |
| 72 | |
Helen Li | d5bb922 | 2018-04-12 15:33:09 | [diff] [blame] | 73 | // TransportClientSocket implementation: |
| 74 | int Bind(const net::IPEndPoint& local_addr) override; |
Brad Lassey | 3a81417 | 2018-04-26 03:30:21 | [diff] [blame] | 75 | // StreamSocket implementation: |
| 76 | int Connect(CompletionOnceCallback callback) override; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 77 | void Disconnect() override; |
| 78 | bool IsConnected() const override; |
| 79 | bool IsConnectedAndIdle() const override; |
| 80 | int GetPeerAddress(IPEndPoint* address) const override; |
| 81 | int GetLocalAddress(IPEndPoint* address) const override; |
tfarina | 42834111 | 2016-09-22 13:38:20 | [diff] [blame] | 82 | const NetLogWithSource& NetLog() const override; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 83 | bool WasEverUsed() const override; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 84 | NextProto GetNegotiatedProtocol() const override; |
| 85 | bool GetSSLInfo(SSLInfo* ssl_info) override; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 86 | int64_t GetTotalReceivedBytes() const override; |
Paul Jensen | 0f49dec | 2017-12-12 23:39:58 | [diff] [blame] | 87 | void ApplySocketTag(const net::SocketTag& tag) override; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 88 | |
| 89 | private: |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 90 | // Returns a net::Error that can be returned by a read or a write. Reads and |
| 91 | // writes return basically the same set of errors, at the TCP socket layer. |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 92 | Error ConsumeReadWriteErrorFromData(); |
| 93 | |
Brad Lassey | 3a81417 | 2018-04-26 03:30:21 | [diff] [blame] | 94 | void OnReadComplete(CompletionOnceCallback callback, int result); |
| 95 | void OnWriteComplete(CompletionOnceCallback callback, int result); |
| 96 | void OnConnectComplete(CompletionOnceCallback callback, int result); |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 97 | |
Matt Menke | be641cd | 2018-03-21 14:50:50 | [diff] [blame] | 98 | // Returns whether all operations should be synchronous. Starts returning |
| 99 | // true once there have been too many async reads and writes, as spinning the |
| 100 | // message loop too often tends to cause fuzzers to time out. |
| 101 | // See https://crbug.com/823012 |
| 102 | bool ForceSync() const; |
| 103 | |
Keishi Hattori | 98eca68 | 2023-03-31 03:10:09 | [diff] [blame] | 104 | raw_ptr<FuzzedDataProvider> data_provider_; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 105 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 106 | // If true, the result of the Connect() call is fuzzed - it can succeed or |
| 107 | // fail with a variety of connection errors, and it can complete synchronously |
| 108 | // or asynchronously. |
| 109 | bool fuzz_connect_result_ = false; |
| 110 | |
| 111 | bool connect_pending_ = false; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 112 | bool read_pending_ = false; |
| 113 | bool write_pending_ = false; |
| 114 | |
| 115 | // This is true when the first callback returning an error is pending in the |
| 116 | // message queue. If true, the socket acts like it's connected until that task |
| 117 | // is run (Or Disconnect() is called), and reads / writes will return the same |
| 118 | // error asynchronously, until it becomes false, at which point they'll return |
| 119 | // it synchronously. |
| 120 | bool error_pending_ = false; |
| 121 | // If this is not OK, all reads/writes will fail with this error. |
| 122 | int net_error_ = ERR_CONNECTION_CLOSED; |
| 123 | |
| 124 | int64_t total_bytes_read_ = 0; |
| 125 | int64_t total_bytes_written_ = 0; |
| 126 | |
Matt Menke | be641cd | 2018-03-21 14:50:50 | [diff] [blame] | 127 | int num_async_reads_and_writes_ = 0; |
| 128 | |
tfarina | 42834111 | 2016-09-22 13:38:20 | [diff] [blame] | 129 | NetLogWithSource net_log_; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 130 | |
mmenke | c951d41 | 2016-04-28 19:05:22 | [diff] [blame] | 131 | IPEndPoint remote_address_; |
| 132 | |
Jeremy Roman | d54000b2 | 2019-07-08 18:40:16 | [diff] [blame] | 133 | base::WeakPtrFactory<FuzzedSocket> weak_factory_{this}; |
mmenke | 99b5717 | 2016-04-14 20:44:33 | [diff] [blame] | 134 | }; |
| 135 | |
| 136 | } // namespace net |
| 137 | |
mmenke | 91c1716 | 2016-06-02 16:03:23 | [diff] [blame] | 138 | #endif // NET_SOCKET_FUZZED_SOCKET_H_ |