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 "base/strings/string_piece.h" 13 #include "net/base/completion_once_callback.h" 14 #include "net/base/ip_endpoint.h" 15 #include "net/base/net_errors.h" 16 #include "net/log/net_log_with_source.h" 17 #include "net/socket/transport_client_socket.h" 18 #include "net/traffic_annotation/network_traffic_annotation.h" 19 20 class FuzzedDataProvider; 21 22 namespace net { 23 24 class IPEndPoint; 25 class IOBuffer; 26 class NetLog; 27 28 // A StreamSocket that uses a FuzzedDataProvider to generate responses. Writes 29 // can succeed synchronously or asynchronously, can write some or all of the 30 // provided data, and can fail with several different errors. Reads can do the 31 // same, but the read data is also generated from the FuzzedDataProvider. The 32 // number of bytes written/read from a single call is currently capped at 255 33 // bytes. 34 // 35 // Reads and writes are executed independently of one another, so to guarantee 36 // the fuzzer behaves the same across repeated runs with the same input, the 37 // reads and writes must be done in a deterministic order and for a 38 // deterministic number of bytes, every time the fuzzer is run with the same 39 // data. 40 class FuzzedSocket : public TransportClientSocket { 41 public: 42 // |data_provider| is used as to determine behavior of the FuzzedSocket. It 43 // must remain valid until after the FuzzedSocket is destroyed. 44 FuzzedSocket(FuzzedDataProvider* data_provider, net::NetLog* net_log); 45 46 FuzzedSocket(const FuzzedSocket&) = delete; 47 FuzzedSocket& operator=(const FuzzedSocket&) = delete; 48 49 ~FuzzedSocket() override; 50 51 // If set to true, the socket will fuzz the result of the Connect() call. 52 // It can fail or succeed, and return synchronously or asynchronously. If 53 // false, Connect() succeeds synchronously. Defaults to false. set_fuzz_connect_result(bool fuzz_connect_result)54 void set_fuzz_connect_result(bool fuzz_connect_result) { 55 fuzz_connect_result_ = fuzz_connect_result; 56 } 57 58 // Sets the remote address the socket claims to be using. set_remote_address(const IPEndPoint & remote_address)59 void set_remote_address(const IPEndPoint& remote_address) { 60 remote_address_ = remote_address; 61 } 62 63 // Socket implementation: 64 int Read(IOBuffer* buf, 65 int buf_len, 66 CompletionOnceCallback callback) override; 67 int Write(IOBuffer* buf, 68 int buf_len, 69 CompletionOnceCallback callback, 70 const NetworkTrafficAnnotationTag& traffic_annotation) override; 71 int SetReceiveBufferSize(int32_t size) override; 72 int SetSendBufferSize(int32_t size) override; 73 74 // TransportClientSocket implementation: 75 int Bind(const net::IPEndPoint& local_addr) override; 76 // StreamSocket implementation: 77 int Connect(CompletionOnceCallback callback) override; 78 void Disconnect() override; 79 bool IsConnected() const override; 80 bool IsConnectedAndIdle() const override; 81 int GetPeerAddress(IPEndPoint* address) const override; 82 int GetLocalAddress(IPEndPoint* address) const override; 83 const NetLogWithSource& NetLog() const override; 84 bool WasEverUsed() const override; 85 bool WasAlpnNegotiated() const override; 86 NextProto GetNegotiatedProtocol() const override; 87 bool GetSSLInfo(SSLInfo* ssl_info) override; 88 int64_t GetTotalReceivedBytes() const override; 89 void ApplySocketTag(const net::SocketTag& tag) override; 90 91 private: 92 // Returns a net::Error that can be returned by a read or a write. Reads and 93 // writes return basically the same set of errors, at the TCP socket layer. 94 Error ConsumeReadWriteErrorFromData(); 95 96 void OnReadComplete(CompletionOnceCallback callback, int result); 97 void OnWriteComplete(CompletionOnceCallback callback, int result); 98 void OnConnectComplete(CompletionOnceCallback callback, int result); 99 100 // Returns whether all operations should be synchronous. Starts returning 101 // true once there have been too many async reads and writes, as spinning the 102 // message loop too often tends to cause fuzzers to time out. 103 // See https://crbug.com/823012 104 bool ForceSync() const; 105 106 raw_ptr<FuzzedDataProvider> data_provider_; 107 108 // If true, the result of the Connect() call is fuzzed - it can succeed or 109 // fail with a variety of connection errors, and it can complete synchronously 110 // or asynchronously. 111 bool fuzz_connect_result_ = false; 112 113 bool connect_pending_ = false; 114 bool read_pending_ = false; 115 bool write_pending_ = false; 116 117 // This is true when the first callback returning an error is pending in the 118 // message queue. If true, the socket acts like it's connected until that task 119 // is run (Or Disconnect() is called), and reads / writes will return the same 120 // error asynchronously, until it becomes false, at which point they'll return 121 // it synchronously. 122 bool error_pending_ = false; 123 // If this is not OK, all reads/writes will fail with this error. 124 int net_error_ = ERR_CONNECTION_CLOSED; 125 126 int64_t total_bytes_read_ = 0; 127 int64_t total_bytes_written_ = 0; 128 129 int num_async_reads_and_writes_ = 0; 130 131 NetLogWithSource net_log_; 132 133 IPEndPoint remote_address_; 134 135 base::WeakPtrFactory<FuzzedSocket> weak_factory_{this}; 136 }; 137 138 } // namespace net 139 140 #endif // NET_SOCKET_FUZZED_SOCKET_H_ 141