1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_SOCKET_FUZZED_SOCKET_H_ 6 #define NET_SOCKET_FUZZED_SOCKET_H_ 7 8 #include <stdint.h> 9 10 #include "base/memory/raw_ptr.h" 11 #include "base/memory/weak_ptr.h" 12 #include "net/base/completion_once_callback.h" 13 #include "net/base/ip_endpoint.h" 14 #include "net/base/net_errors.h" 15 #include "net/log/net_log_with_source.h" 16 #include "net/socket/transport_client_socket.h" 17 #include "net/traffic_annotation/network_traffic_annotation.h" 18 19 class FuzzedDataProvider; 20 21 namespace net { 22 23 class IPEndPoint; 24 class IOBuffer; 25 class NetLog; 26 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. 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. 39 class FuzzedSocket : public TransportClientSocket { 40 public: 41 // |data_provider| is used as to determine behavior of the FuzzedSocket. It 42 // must remain valid until after the FuzzedSocket is destroyed. 43 FuzzedSocket(FuzzedDataProvider* data_provider, net::NetLog* net_log); 44 45 FuzzedSocket(const FuzzedSocket&) = delete; 46 FuzzedSocket& operator=(const FuzzedSocket&) = delete; 47 48 ~FuzzedSocket() override; 49 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. set_fuzz_connect_result(bool fuzz_connect_result)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. set_remote_address(const IPEndPoint & remote_address)58 void set_remote_address(const IPEndPoint& remote_address) { 59 remote_address_ = remote_address; 60 } 61 62 // Socket implementation: 63 int Read(IOBuffer* buf, 64 int buf_len, 65 CompletionOnceCallback callback) override; 66 int Write(IOBuffer* buf, 67 int buf_len, 68 CompletionOnceCallback callback, 69 const NetworkTrafficAnnotationTag& traffic_annotation) override; 70 int SetReceiveBufferSize(int32_t size) override; 71 int SetSendBufferSize(int32_t size) override; 72 73 // TransportClientSocket implementation: 74 int Bind(const net::IPEndPoint& local_addr) override; 75 // StreamSocket implementation: 76 int Connect(CompletionOnceCallback callback) override; 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; 82 const NetLogWithSource& NetLog() const override; 83 bool WasEverUsed() const override; 84 NextProto GetNegotiatedProtocol() const override; 85 bool GetSSLInfo(SSLInfo* ssl_info) override; 86 int64_t GetTotalReceivedBytes() const override; 87 void ApplySocketTag(const net::SocketTag& tag) override; 88 89 private: 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. 92 Error ConsumeReadWriteErrorFromData(); 93 94 void OnReadComplete(CompletionOnceCallback callback, int result); 95 void OnWriteComplete(CompletionOnceCallback callback, int result); 96 void OnConnectComplete(CompletionOnceCallback callback, int result); 97 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 104 raw_ptr<FuzzedDataProvider> data_provider_; 105 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; 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 127 int num_async_reads_and_writes_ = 0; 128 129 NetLogWithSource net_log_; 130 131 IPEndPoint remote_address_; 132 133 base::WeakPtrFactory<FuzzedSocket> weak_factory_{this}; 134 }; 135 136 } // namespace net 137 138 #endif // NET_SOCKET_FUZZED_SOCKET_H_ 139