• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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