Line data Source code
1 : #if !FD_HAS_HOSTED
2 : #error "This target requires FD_HAS_HOSTED"
3 : #endif
4 :
5 : #include <assert.h>
6 : #include <stdio.h>
7 : #include <stdlib.h>
8 : #include <unistd.h>
9 :
10 : #include "../../../util/sanitize/fd_fuzz.h"
11 :
12 : #pragma GCC diagnostic ignored "-Wunused-function"
13 : #include "../fd_quic.h"
14 : #include "../fd_quic_private.h"
15 : #include "../fd_quic_proto.h"
16 :
17 : #include "fd_quic_test_helpers.h"
18 : #include "../../tls/test_tls_helper.h"
19 :
20 : #include "../../../ballet/x509/fd_x509_mock.h"
21 :
22 : fd_quic_t *server_quic = NULL;
23 :
24 : uchar scratch[0x4000];
25 : size_t scratch_sz = 0x4000;
26 :
27 : fd_aio_t _aio[1];
28 :
29 :
30 234795 : ulong test_clock(void *ctx) {
31 234795 : (void)ctx;
32 234795 : return (ulong)fd_log_wallclock();
33 234795 : }
34 :
35 : int test_aio_send_func(void *ctx, fd_aio_pkt_info_t const *batch,
36 33 : ulong batch_cnt, ulong *opt_batch_idx, int flush) {
37 33 : (void)flush;
38 33 : (void)batch;
39 33 : (void)batch_cnt;
40 33 : (void)opt_batch_idx;
41 33 : (void)ctx;
42 33 : return 0;
43 33 : }
44 :
45 38580 : uint send_packet(uchar const *payload, size_t payload_sz) {
46 :
47 38580 : if (FD_UNLIKELY(payload_sz <= 0L)) {
48 21660 : return 0u;
49 21660 : }
50 :
51 16920 : uchar *cur_ptr = scratch;
52 16920 : ulong cur_sz = scratch_sz;
53 :
54 16920 : fd_quic_pkt_t pkt;
55 :
56 16920 : memcpy(pkt.eth->dst, "\x52\xF1\x7E\xDA\x2C\xE0", 6);
57 16920 : memcpy(pkt.eth->src, "\x52\xF1\x7E\xDA\x2C\xE0", 6);
58 16920 : pkt.eth->net_type = FD_ETH_HDR_TYPE_IP;
59 :
60 16920 : pkt.ip4->verihl = FD_IP4_VERIHL(4,5);
61 16920 : pkt.ip4->tos = 0;
62 16920 : pkt.ip4->net_tot_len = (ushort)(20 + 8 + payload_sz);
63 16920 : pkt.ip4->net_id = 0;
64 16920 : pkt.ip4->net_frag_off = 0x4000u;
65 16920 : pkt.ip4->ttl = 64; /* TODO make configurable */
66 16920 : pkt.ip4->protocol = FD_IP4_HDR_PROTOCOL_UDP;
67 16920 : pkt.ip4->check = 0;
68 :
69 16920 : pkt.udp->net_sport = 0x2;
70 16920 : pkt.udp->net_dport = 0x1;
71 16920 : pkt.udp->net_len = (ushort)(8 + payload_sz);
72 16920 : pkt.udp->check = 0x0000;
73 :
74 16920 : ulong rc = fd_quic_encode_eth(cur_ptr, cur_sz, pkt.eth);
75 16920 : if (FD_UNLIKELY(rc == FD_QUIC_PARSE_FAIL)) {
76 0 : return 1;
77 0 : }
78 :
79 16920 : cur_ptr += rc;
80 16920 : cur_sz -= rc;
81 :
82 16920 : rc = fd_quic_encode_ip4(cur_ptr, cur_sz, pkt.ip4);
83 16920 : if (FD_UNLIKELY(rc == FD_QUIC_PARSE_FAIL)) {
84 0 : return 1;
85 0 : }
86 :
87 : /* Compute checksum over network byte order header */
88 16920 : fd_ip4_hdr_t *ip4_encoded = (fd_ip4_hdr_t *)fd_type_pun(cur_ptr);
89 16920 : ip4_encoded->check = (ushort)fd_ip4_hdr_check_fast(ip4_encoded);
90 :
91 16920 : cur_ptr += rc;
92 16920 : cur_sz -= rc;
93 :
94 16920 : rc = fd_quic_encode_udp(cur_ptr, cur_sz, pkt.udp);
95 16920 : if (FD_UNLIKELY(rc == FD_QUIC_PARSE_FAIL)) {
96 0 : return 1;
97 0 : }
98 :
99 16920 : cur_ptr += rc;
100 16920 : cur_sz -= rc;
101 :
102 16920 : if (FD_UNLIKELY((ulong)payload_sz > cur_sz)) {
103 0 : return FD_QUIC_FAILED;
104 0 : }
105 16920 : fd_memcpy(cur_ptr, payload, (ulong)payload_sz);
106 :
107 16920 : cur_ptr += (ulong)payload_sz;
108 16920 : cur_sz -= (ulong)payload_sz;
109 :
110 16920 : fd_aio_pkt_info_t batch = {.buf = (void *)scratch,
111 16920 : .buf_sz = (ushort)(scratch_sz - cur_sz)};
112 :
113 16920 : fd_quic_aio_cb_receive((void *)server_quic, &batch, 1, NULL, 0);
114 :
115 16920 : return FD_QUIC_SUCCESS; /* success */
116 16920 : }
117 :
118 1200 : void init_quic(void) {
119 1200 : void *ctx = (void *)0x1234UL;
120 1200 : void *shaio = fd_aio_new(_aio, ctx, test_aio_send_func);
121 1200 : assert( shaio );
122 1200 : fd_aio_t *aio = fd_aio_join(shaio);
123 1200 : assert(aio);
124 :
125 1200 : server_quic->cb.now = test_clock;
126 1200 : server_quic->cb.now_ctx = NULL;
127 :
128 1200 : fd_quic_set_aio_net_tx(server_quic, aio);
129 1200 : fd_quic_init( server_quic );
130 1200 : }
131 :
132 : void
133 0 : destroy_quic( void ) {
134 0 : fd_quic_fini( server_quic );
135 0 : }
136 :
137 3 : int LLVMFuzzerInitialize(int *argc, char ***argv) {
138 : /* Set up shell without signal handlers */
139 3 : putenv("FD_LOG_BACKTRACE=0");
140 3 : fd_boot(argc, argv);
141 3 : atexit(fd_halt);
142 :
143 : /* Use unoptimized wksp memory */
144 :
145 3 : ulong wksp_sz = 13107200UL * 2;
146 :
147 3 : uchar * mem = aligned_alloc( 4096UL, wksp_sz );
148 3 : assert( mem );
149 :
150 3 : ulong part_max = fd_wksp_part_max_est( wksp_sz, 64UL<<10 );
151 3 : assert( part_max );
152 3 : ulong data_max = fd_wksp_data_max_est( wksp_sz, 64UL<<10 );
153 :
154 3 : fd_wksp_t * wksp = fd_wksp_join( fd_wksp_new( mem, "wksp", 42U, part_max, data_max ) );
155 3 : assert( wksp );
156 :
157 3 : int shmem_err = fd_shmem_join_anonymous( "wksp", FD_SHMEM_JOIN_MODE_READ_WRITE, wksp, mem, 4096UL, wksp_sz/4096UL );
158 3 : assert( !shmem_err );
159 :
160 3 : fd_quic_limits_t const quic_limits = {.conn_cnt = 10,
161 3 : .conn_id_cnt = 10,
162 3 : .handshake_cnt = 10,
163 3 : .rx_stream_cnt = 10,
164 3 : .stream_pool_cnt = 640,
165 3 : .inflight_pkt_cnt = 1024,
166 3 : .tx_buf_sz = 1 << 14};
167 :
168 3 : ulong quic_footprint = fd_quic_footprint(&quic_limits);
169 3 : assert( quic_footprint );
170 :
171 3 : fd_rng_t _rng[1]; fd_rng_t * rng = fd_rng_join( fd_rng_new( _rng, 0U, 0UL ) );
172 3 : server_quic = fd_quic_new_anonymous(wksp, &quic_limits, FD_QUIC_ROLE_SERVER, rng);
173 3 : assert( server_quic );
174 3 : fd_rng_delete( fd_rng_leave( rng ) );
175 :
176 3 : fd_quic_config_t *server_config = &server_quic->config;
177 3 : server_config->idle_timeout = 5e6;
178 3 : server_config->retry = 1;
179 :
180 3 : server_quic->cb.now = test_clock;
181 3 : server_quic->cb.now_ctx = NULL;
182 :
183 3 : server_quic->config.initial_rx_max_stream_data = 1 << 14;
184 : // server_quic->config.retry = 1;
185 :
186 3 : return 0;
187 3 : }
188 :
189 1200 : int LLVMFuzzerTestOneInput(uchar const *data, ulong size) {
190 1200 : ulong s = size;
191 1200 : uchar const *ptr = data;
192 :
193 1200 : init_quic();
194 :
195 39780 : while (s > 2) {
196 39360 : FD_FUZZ_MUST_BE_COVERED;
197 39360 : ushort payload_sz = (ushort)( ptr[0] + ( ptr[1] << 8u ) );
198 39360 : ptr += 2;
199 39360 : s -= 2;
200 39360 : if (payload_sz <= s) {
201 38580 : send_packet(ptr, payload_sz);
202 38580 : FD_FUZZ_MUST_BE_COVERED;
203 38580 : ptr += payload_sz;
204 38580 : s -= payload_sz;
205 38580 : } else {
206 780 : FD_FUZZ_MUST_BE_COVERED;
207 780 : fd_quic_fini(server_quic);
208 780 : return 0;
209 780 : }
210 39360 : }
211 :
212 420 : fd_quic_fini(server_quic);
213 :
214 420 : FD_FUZZ_MUST_BE_COVERED;
215 420 : return 0;
216 1200 : }
|