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 NextProto GetNegotiatedProtocol() const override; 86 bool GetSSLInfo(SSLInfo* ssl_info) override; 87 int64_t GetTotalReceivedBytes() const override; 88 void ApplySocketTag(const net::SocketTag& tag) override; 89 90 private: 91 // Returns a net::Error that can be returned by a read or a write. Reads and 92 // writes return basically the same set of errors, at the TCP socket layer. 93 Error ConsumeReadWriteErrorFromData(); 94 95 void OnReadComplete(CompletionOnceCallback callback, int result); 96 void OnWriteComplete(CompletionOnceCallback callback, int result); 97 void OnConnectComplete(CompletionOnceCallback callback, int result); 98 99 // Returns whether all operations should be synchronous. Starts returning 100 // true once there have been too many async reads and writes, as spinning the 101 // message loop too often tends to cause fuzzers to time out. 102 // See https://crbug.com/823012 103 bool ForceSync() const; 104 105 raw_ptr<FuzzedDataProvider> data_provider_; 106 107 // If true, the result of the Connect() call is fuzzed - it can succeed or 108 // fail with a variety of connection errors, and it can complete synchronously 109 // or asynchronously. 110 bool fuzz_connect_result_ = false; 111 112 bool connect_pending_ = false; 113 bool read_pending_ = false; 114 bool write_pending_ = false; 115 116 // This is true when the first callback returning an error is pending in the 117 // message queue. If true, the socket acts like it's connected until that task 118 // is run (Or Disconnect() is called), and reads / writes will return the same 119 // error asynchronously, until it becomes false, at which point they'll return 120 // it synchronously. 121 bool error_pending_ = false; 122 // If this is not OK, all reads/writes will fail with this error. 123 int net_error_ = ERR_CONNECTION_CLOSED; 124 125 int64_t total_bytes_read_ = 0; 126 int64_t total_bytes_written_ = 0; 127 128 int num_async_reads_and_writes_ = 0; 129 130 NetLogWithSource net_log_; 131 132 IPEndPoint remote_address_; 133 134 base::WeakPtrFactory<FuzzedSocket> weak_factory_{this}; 135 }; 136 137 } // namespace net 138 139 #endif // NET_SOCKET_FUZZED_SOCKET_H_ 140