xref: /aosp_15_r20/external/cronet/net/socket/fuzzed_socket.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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