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 :
19 : fd_quic_t *server_quic = NULL;
20 :
21 : uchar scratch[0x4000];
22 : size_t scratch_sz = 0x4000;
23 :
24 : fd_aio_t _aio[1];
25 :
26 : int test_aio_send_func(void *ctx, fd_aio_pkt_info_t const *batch,
27 33 : ulong batch_cnt, ulong *opt_batch_idx, int flush) {
28 33 : (void)flush;
29 33 : (void)batch;
30 33 : (void)batch_cnt;
31 33 : (void)opt_batch_idx;
32 33 : (void)ctx;
33 33 : return 0;
34 33 : }
35 :
36 38580 : uint send_packet(uchar const *payload, size_t payload_sz) {
37 :
38 38580 : if (FD_UNLIKELY(payload_sz <= 0L)) {
39 21660 : return 0u;
40 21660 : }
41 :
42 16920 : uchar *cur_ptr = scratch;
43 16920 : ulong cur_sz = scratch_sz;
44 :
45 16920 : fd_quic_pkt_t pkt;
46 :
47 16920 : pkt.ip4->verihl = FD_IP4_VERIHL(4,5);
48 16920 : pkt.ip4->tos = 0;
49 16920 : pkt.ip4->net_tot_len = (ushort)(20 + 8 + payload_sz);
50 16920 : pkt.ip4->net_id = 0;
51 16920 : pkt.ip4->net_frag_off = 0x4000u;
52 16920 : pkt.ip4->ttl = 64; /* TODO make configurable */
53 16920 : pkt.ip4->protocol = FD_IP4_HDR_PROTOCOL_UDP;
54 16920 : pkt.ip4->check = 0;
55 :
56 16920 : pkt.udp->net_sport = 0x2;
57 16920 : pkt.udp->net_dport = 0x1;
58 16920 : pkt.udp->net_len = (ushort)(8 + payload_sz);
59 16920 : pkt.udp->check = 0x0000;
60 :
61 16920 : ulong rc = fd_quic_encode_ip4(cur_ptr, cur_sz, pkt.ip4);
62 16920 : if (FD_UNLIKELY(rc == FD_QUIC_PARSE_FAIL)) {
63 0 : return 1;
64 0 : }
65 :
66 : /* Compute checksum over network byte order header */
67 16920 : fd_ip4_hdr_t *ip4_encoded = (fd_ip4_hdr_t *)fd_type_pun(cur_ptr);
68 16920 : ip4_encoded->check = (ushort)fd_ip4_hdr_check_fast(ip4_encoded);
69 :
70 16920 : cur_ptr += rc;
71 16920 : cur_sz -= rc;
72 :
73 16920 : rc = fd_quic_encode_udp(cur_ptr, cur_sz, pkt.udp);
74 16920 : if (FD_UNLIKELY(rc == FD_QUIC_PARSE_FAIL)) {
75 0 : return 1;
76 0 : }
77 :
78 16920 : cur_ptr += rc;
79 16920 : cur_sz -= rc;
80 :
81 16920 : if (FD_UNLIKELY((ulong)payload_sz > cur_sz)) {
82 0 : return FD_QUIC_FAILED;
83 0 : }
84 16920 : fd_memcpy(cur_ptr, payload, (ulong)payload_sz);
85 :
86 16920 : cur_ptr += (ulong)payload_sz;
87 16920 : cur_sz -= (ulong)payload_sz;
88 :
89 16920 : fd_quic_process_packet( server_quic, scratch, scratch_sz - cur_sz );
90 :
91 16920 : return FD_QUIC_SUCCESS; /* success */
92 16920 : }
93 :
94 1200 : void init_quic(void) {
95 1200 : void *ctx = (void *)0x1234UL;
96 1200 : void *shaio = fd_aio_new(_aio, ctx, test_aio_send_func);
97 1200 : assert( shaio );
98 0 : fd_aio_t *aio = fd_aio_join(shaio);
99 1200 : assert(aio);
100 :
101 0 : fd_quic_set_aio_net_tx(server_quic, aio);
102 1200 : fd_quic_init( server_quic );
103 1200 : }
104 :
105 : void
106 0 : destroy_quic( void ) {
107 0 : fd_quic_fini( server_quic );
108 0 : }
109 :
110 3 : int LLVMFuzzerInitialize(int *argc, char ***argv) {
111 : /* Set up shell without signal handlers */
112 3 : putenv("FD_LOG_BACKTRACE=0");
113 3 : fd_boot(argc, argv);
114 3 : # ifndef FD_DEBUG_MODE
115 3 : fd_log_level_core_set(3); /* crash on warning log */
116 3 : # endif
117 3 : atexit(fd_halt);
118 :
119 : /* Use unoptimized wksp memory */
120 :
121 3 : ulong wksp_sz = 13107200UL * 2;
122 :
123 3 : uchar * mem = aligned_alloc( 4096UL, wksp_sz );
124 3 : assert( mem );
125 :
126 0 : ulong part_max = fd_wksp_part_max_est( wksp_sz, 64UL<<10 );
127 3 : assert( part_max );
128 0 : ulong data_max = fd_wksp_data_max_est( wksp_sz, 64UL<<10 );
129 :
130 3 : fd_wksp_t * wksp = fd_wksp_join( fd_wksp_new( mem, "wksp", 42U, part_max, data_max ) );
131 3 : assert( wksp );
132 :
133 3 : int shmem_err = fd_shmem_join_anonymous( "wksp", FD_SHMEM_JOIN_MODE_READ_WRITE, wksp, mem, 4096UL, wksp_sz/4096UL );
134 3 : assert( !shmem_err );
135 :
136 0 : fd_quic_limits_t const quic_limits = {.conn_cnt = 10,
137 3 : .conn_id_cnt = 10,
138 3 : .handshake_cnt = 10,
139 3 : .stream_pool_cnt = 640,
140 3 : .inflight_pkt_cnt = 1024,
141 3 : .tx_buf_sz = 1 << 14};
142 :
143 3 : ulong quic_footprint = fd_quic_footprint(&quic_limits);
144 3 : assert( quic_footprint );
145 :
146 0 : fd_rng_t _rng[1]; fd_rng_t * rng = fd_rng_join( fd_rng_new( _rng, 0U, 0UL ) );
147 3 : server_quic = fd_quic_new_anonymous(wksp, &quic_limits, FD_QUIC_ROLE_SERVER, rng);
148 3 : assert( server_quic );
149 0 : fd_rng_delete( fd_rng_leave( rng ) );
150 :
151 3 : fd_quic_config_t *server_config = &server_quic->config;
152 3 : server_config->idle_timeout = 5e6;
153 3 : server_config->retry = 1;
154 :
155 3 : server_quic->config.initial_rx_max_stream_data = 1 << 14;
156 : // server_quic->config.retry = 1;
157 :
158 3 : return 0;
159 3 : }
160 :
161 1200 : int LLVMFuzzerTestOneInput(uchar const *data, ulong size) {
162 1200 : ulong s = size;
163 1200 : uchar const *ptr = data;
164 :
165 1200 : init_quic();
166 :
167 39780 : while (s > 2) {
168 39360 : FD_FUZZ_MUST_BE_COVERED;
169 39360 : ushort payload_sz = (ushort)( ptr[0] + ( ptr[1] << 8u ) );
170 39360 : ptr += 2;
171 39360 : s -= 2;
172 39360 : if (payload_sz <= s) {
173 38580 : send_packet(ptr, payload_sz);
174 38580 : FD_FUZZ_MUST_BE_COVERED;
175 38580 : ptr += payload_sz;
176 38580 : s -= payload_sz;
177 38580 : } else {
178 780 : FD_FUZZ_MUST_BE_COVERED;
179 780 : fd_quic_fini(server_quic);
180 780 : return 0;
181 780 : }
182 39360 : }
183 :
184 420 : fd_quic_fini(server_quic);
185 :
186 420 : FD_FUZZ_MUST_BE_COVERED;
187 420 : return 0;
188 1200 : }
|