LCOV - code coverage report
Current view: top level - waltz/quic/tests - fuzz_quic.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 127 138 92.0 %
Date: 2024-11-13 11:58:15 Functions: 6 7 85.7 %

          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 : }

Generated by: LCOV version 1.14