Line data Source code
1 : #include "fd_genesis_parse.h" 2 : #include "fd_runtime_const.h" 3 : #include <assert.h> 4 : #include <stdlib.h> 5 : 6 : static uchar genesis_buf[ FD_GENESIS_MAX_MESSAGE_SIZE ] __attribute__((aligned(alignof(fd_genesis_t)))); 7 : 8 : int 9 : LLVMFuzzerInitialize( int * argc, 10 12 : char *** argv ) { 11 : /* Set up shell without signal handlers */ 12 12 : putenv( "FD_LOG_BACKTRACE=0" ); 13 12 : fd_boot( argc, argv ); 14 12 : fd_log_level_stderr_set(4); 15 12 : atexit( fd_halt ); 16 12 : return 0; 17 12 : } 18 : 19 : static int 20 0 : genesis_accounts_check( uchar genesis_buf[ static FD_GENESIS_MAX_MESSAGE_SIZE ] ) { 21 : 22 0 : fd_genesis_t * genesis = fd_type_pun( genesis_buf ); 23 0 : ulong genesis_sz = genesis->total_sz; 24 0 : ulong lowest_expected_offset = sizeof(fd_genesis_t); 25 : 26 0 : if( FD_UNLIKELY( genesis_sz>FD_GENESIS_MAX_MESSAGE_SIZE ) ) return 0; 27 : 28 0 : if( FD_UNLIKELY( genesis->accounts_len>FD_GENESIS_ACCOUNT_MAX_COUNT ) ) return 0; 29 0 : for( ulong i=0UL; i<genesis->accounts_len; i++ ) { 30 0 : ulong account_off = genesis->accounts_off[ i ]; 31 0 : if( FD_UNLIKELY( account_off>genesis_sz ) ) return 0; 32 0 : if( FD_UNLIKELY( account_off<lowest_expected_offset ) ) return 0; 33 : 34 0 : fd_genesis_account_t * account = fd_type_pun( genesis_buf+account_off ); 35 0 : if( FD_UNLIKELY( account->meta.dlen>FD_RUNTIME_ACC_SZ_MAX ) ) return 0; 36 : 37 0 : ulong next_offset = account_off+sizeof(fd_genesis_account_t)+account->meta.dlen; 38 0 : if( FD_UNLIKELY( next_offset<lowest_expected_offset ) ) return 0; 39 0 : lowest_expected_offset = next_offset; 40 0 : } 41 : 42 0 : if( FD_UNLIKELY( genesis->builtin_len>FD_GENESIS_BUILTIN_MAX_COUNT ) ) return 0; 43 0 : for( ulong i=0UL; i<genesis->builtin_len; i++ ) { 44 0 : ulong builtin_off = genesis->builtin_off[ i ]; 45 0 : if( FD_UNLIKELY( builtin_off>genesis_sz ) ) return 0; 46 0 : if( FD_UNLIKELY( builtin_off<lowest_expected_offset ) ) return 0; 47 : 48 0 : fd_genesis_builtin_t * builtin = fd_type_pun( genesis_buf+builtin_off ); 49 0 : if( FD_UNLIKELY( builtin->data_len>FD_RUNTIME_ACC_SZ_MAX ) ) return 0; 50 : 51 0 : ulong next_offset = builtin_off+sizeof(fd_genesis_builtin_t)+builtin->data_len; 52 0 : if( FD_UNLIKELY( next_offset<lowest_expected_offset ) ) return 0; 53 0 : lowest_expected_offset = next_offset; 54 0 : } 55 : 56 0 : if( FD_UNLIKELY( lowest_expected_offset>genesis_sz ) ) return 0; 57 0 : return 1; 58 0 : } 59 : 60 : int 61 : LLVMFuzzerTestOneInput( uchar const * data, 62 : ulong size ) { 63 : 64 : if( !fd_genesis_parse( genesis_buf, data, size ) ) return 0; 65 : /* In the genesis, the only two fields that are not fixed size are the 66 : accounts and the built-in accounts. The offsets and bounds of each 67 : of the accounts are checked here. */ 68 : assert( genesis_accounts_check( genesis_buf ) ); 69 : 70 : return 0; 71 : }