LCOV - code coverage report
Current view: top level - flamenco/gossip - fuzz_gossip_msg_parse.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 7 70 10.0 %
Date: 2025-12-29 05:22:51 Functions: 1 5 20.0 %

          Line data    Source code
       1             : #include "fd_gossip_private.h"
       2             : #include <assert.h>
       3             : #include <stdlib.h>
       4             : 
       5             : int
       6             : LLVMFuzzerInitialize( int  *   argc,
       7          12 :                       char *** argv ) {
       8             :   /* Set up shell without signal handlers */
       9          12 :   putenv( "FD_LOG_BACKTRACE=0" );
      10          12 :   fd_boot( argc, argv );
      11          12 :   fd_log_level_stderr_set(4);
      12          12 :   atexit( fd_halt );
      13          12 :   return 0;
      14          12 : }
      15             : 
      16             : static int
      17             : bounds_check_arr( ulong data_sz,
      18             :                   ulong ele_off,
      19             :                   ulong ele_sz,
      20           0 :                   ulong ele_cnt ) {
      21           0 :   ulong ele_tot;
      22           0 :   if( FD_UNLIKELY( __builtin_umull_overflow( ele_sz, ele_cnt, &ele_tot ) ) )
      23           0 :     return 0;
      24           0 :   ulong ele_hi;
      25           0 :   if( FD_UNLIKELY( __builtin_uaddl_overflow( ele_off, ele_tot, &ele_hi ) ) )
      26           0 :     return 0;
      27           0 :   if( FD_UNLIKELY( ele_hi>data_sz ) )
      28           0 :     return 0;
      29           0 :   return 1;
      30           0 : }
      31             : 
      32             : static int
      33             : bounds_check( ulong data_sz,
      34             :               ulong ele_off,
      35           0 :               ulong ele_sz ) {
      36           0 :   ulong ele_hi;
      37           0 :   if( FD_UNLIKELY( __builtin_uaddl_overflow( ele_off, ele_sz, &ele_hi ) ) )
      38           0 :     return 0;
      39           0 :   if( FD_UNLIKELY( ele_hi>data_sz ) )
      40           0 :     return 0;
      41           0 :   return 1;
      42           0 : }
      43             : 
      44             : static void
      45             : check_view_snapshot_hashes( ulong size,
      46           0 :                             fd_gossip_view_snapshot_hashes_t const * v ) {
      47           0 :   assert( bounds_check( size, v->full_off, 40UL ) );
      48           0 :   assert( bounds_check_arr( size, v->inc_off, 40UL, v->inc_len ) );
      49           0 : }
      50             : 
      51             : static void
      52             : check_view_crds_value( uchar const * data,
      53             :                        ulong         size,
      54           0 :                        fd_gossip_view_crds_value_t const * v ) {
      55           0 :   (void)data;
      56           0 :   assert( bounds_check( size, v->pubkey_off, sizeof(fd_pubkey_t) ) );
      57           0 :   assert( bounds_check_arr( size, v->value_off, 1UL, v->length ) );
      58           0 :   switch( v->tag ) {
      59           0 :   case FD_GOSSIP_VALUE_LEGACY_CONTACT_INFO:
      60           0 :     break;
      61           0 :   case FD_GOSSIP_VALUE_VOTE:
      62           0 :     assert( bounds_check_arr( size, v->vote->txn_off, 1UL, v->vote->txn_sz ) );
      63           0 :     break;
      64           0 :   case FD_GOSSIP_VALUE_LOWEST_SLOT:
      65           0 :     break;
      66           0 :   case FD_GOSSIP_VALUE_LEGACY_SNAPSHOT_HASHES:
      67           0 :     break;
      68           0 :   case FD_GOSSIP_VALUE_ACCOUNT_HASHES:
      69           0 :     break;
      70           0 :   case FD_GOSSIP_VALUE_EPOCH_SLOTS:
      71           0 :     break;
      72           0 :   case FD_GOSSIP_VALUE_LEGACY_VERSION:
      73           0 :     break;
      74           0 :   case FD_GOSSIP_VALUE_VERSION:
      75           0 :     break;
      76           0 :   case FD_GOSSIP_VALUE_NODE_INSTANCE:
      77           0 :     break;
      78           0 :   case FD_GOSSIP_VALUE_DUPLICATE_SHRED:
      79           0 :     assert( bounds_check_arr( size, v->duplicate_shred->chunk_off, 1UL, v->duplicate_shred->chunk_len ) );
      80           0 :     break;
      81           0 :   case FD_GOSSIP_VALUE_INC_SNAPSHOT_HASHES:
      82           0 :     check_view_snapshot_hashes( size, v->snapshot_hashes );
      83           0 :     break;
      84           0 :   case FD_GOSSIP_VALUE_CONTACT_INFO:
      85           0 :     break;
      86           0 :   case FD_GOSSIP_VALUE_RESTART_LAST_VOTED_FORK_SLOTS:
      87           0 :     break;
      88           0 :   case FD_GOSSIP_VALUE_RESTART_HEAVIEST_FORK:
      89           0 :     break;
      90           0 :   default:
      91           0 :     FD_LOG_CRIT(( "invalid CRDS value tag %u", v->tag ));
      92           0 :   }
      93           0 : }
      94             : 
      95             : int
      96             : LLVMFuzzerTestOneInput( uchar const * data,
      97             :                         ulong         size ) {
      98             :   if( FD_UNLIKELY( size>1232UL ) ) return 0;
      99             : 
     100             :   fd_gossip_view_t view[1];
     101             :   if( !fd_gossip_msg_parse( view, data, size ) ) return 0;
     102             :   switch( view->tag ) {
     103             :   case FD_GOSSIP_MESSAGE_PULL_REQUEST:
     104             :     assert( bounds_check_arr( size, view->pull_request->bloom_keys_offset, sizeof(ulong), view->pull_request->bloom_keys_len ) );
     105             :     assert( bounds_check_arr( size, view->pull_request->bloom_bits_offset, sizeof(uchar), fd_ulong_align_up( view->pull_request->bloom_bits_cnt, 8UL )/8UL ) );
     106             :     break;
     107             :   case FD_GOSSIP_MESSAGE_PULL_RESPONSE:
     108             :     assert( bounds_check( size, view->pull_response->from_off, sizeof(fd_pubkey_t) ) );
     109             :     for( ulong i=0UL; i<(view->pull_response->crds_values_len); i++ ) {
     110             :       check_view_crds_value( data, size, &view->pull_response->crds_values[i] );
     111             :     }
     112             :     break;
     113             :   case FD_GOSSIP_MESSAGE_PUSH:
     114             :     assert( bounds_check( size, view->push->from_off, sizeof(fd_pubkey_t) ) );
     115             :     for( ulong i=0UL; i<(view->push->crds_values_len); i++ ) {
     116             :       check_view_crds_value( data, size, &view->push->crds_values[i] );
     117             :     }
     118             :     break;
     119             :   case FD_GOSSIP_MESSAGE_PRUNE:
     120             :     assert( bounds_check( size, view->prune->pubkey_off, sizeof(fd_pubkey_t) ) );
     121             :     assert( bounds_check_arr( size, view->prune->origins_off, sizeof(fd_pubkey_t), view->prune->origins_len ) );
     122             :     assert( bounds_check( size, view->prune->destination_off, sizeof(fd_pubkey_t) ) );
     123             :     assert( bounds_check( size, view->prune->signature_off, 64UL ) );
     124             :     break;
     125             :   case FD_GOSSIP_MESSAGE_PING:
     126             :     assert( bounds_check( size, view->ping_pong_off, sizeof(fd_gossip_view_ping_t) ) );
     127             :     break;
     128             :   case FD_GOSSIP_MESSAGE_PONG:
     129             :     assert( bounds_check( size, view->ping_pong_off, sizeof(fd_gossip_view_pong_t) ) );
     130             :     break;
     131             :   default:
     132             :     FD_LOG_CRIT(( "invalid gossip msg tag %u", view->tag ));
     133             :   }
     134             : 
     135             :   return 0;
     136             : }

Generated by: LCOV version 1.14