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/fd_util.h" 11 : #include "../../util/sanitize/fd_fuzz.h" 12 : #include "picohttpparser.h" 13 : 14 : int 15 : LLVMFuzzerInitialize( int * argc, 16 18 : char *** argv ) { 17 : /* Set up shell without signal handlers */ 18 18 : putenv( "FD_LOG_BACKTRACE=0" ); 19 18 : fd_boot( argc, argv ); 20 18 : atexit( fd_halt ); 21 : 22 : /* Disable parsing error logging */ 23 18 : fd_log_level_stderr_set(4); 24 18 : return 0; 25 18 : } 26 : 27 6 : #define HEADER_CAP (32UL) 28 : 29 : int 30 : LLVMFuzzerTestOneInput( uchar const * data, 31 3 : ulong size ) { 32 : 33 : /* parse request in one go */ 34 : 35 3 : do { 36 3 : char const * method; 37 3 : ulong method_len; 38 3 : char const * path; 39 3 : ulong path_len; 40 3 : int minor_version; 41 3 : struct phr_header headers[ HEADER_CAP ]; 42 3 : ulong header_cnt = HEADER_CAP; 43 : 44 3 : int res = phr_parse_request( 45 3 : (char const *)data, size, 46 3 : &method, &method_len, 47 3 : &path, &path_len, 48 3 : &minor_version, 49 3 : headers, &header_cnt, 0UL ); 50 : 51 3 : if( res==0 ) { 52 0 : FD_FUZZ_MUST_BE_COVERED; 53 0 : assert( method_len < size ); 54 0 : assert( path_len < size ); 55 0 : assert( header_cnt <= HEADER_CAP ); 56 0 : for( ulong i=0UL; i<header_cnt; i++ ) { 57 0 : assert( headers[i].name_len < size ); 58 0 : assert( headers[i].value_len < size ); 59 0 : } 60 3 : } else { 61 3 : FD_FUZZ_MUST_BE_COVERED; 62 3 : } 63 3 : } while(0); 64 : 65 : /* parse request byte by byte */ 66 : 67 3 : do { 68 3 : char const * method; 69 3 : ulong method_len; 70 3 : char const * path; 71 3 : ulong path_len; 72 3 : int minor_version; 73 3 : struct phr_header headers[ HEADER_CAP ]; 74 3 : ulong header_cnt = HEADER_CAP; 75 3 : int ok = 0; 76 : 77 15 : for( ulong cursor=0UL; cursor<size; cursor++ ) { 78 15 : FD_FUZZ_MUST_BE_COVERED; 79 15 : int res = phr_parse_request( 80 15 : (char const *)data + cursor, 1UL, 81 15 : &method, &method_len, 82 15 : &path, &path_len, 83 15 : &minor_version, 84 15 : headers, &header_cnt, 0UL ); 85 15 : if( res>0 ) { 86 0 : ok = 1; 87 0 : break; 88 0 : } 89 15 : if( res==-1 ) break; 90 12 : assert( res==-2 ); 91 12 : } 92 : 93 3 : if( ok ) { 94 0 : FD_FUZZ_MUST_BE_COVERED; 95 0 : assert( method_len < size ); 96 0 : assert( path_len < size ); 97 0 : assert( header_cnt <= HEADER_CAP ); 98 0 : for( ulong i=0UL; i<header_cnt; i++ ) { 99 0 : assert( headers[i].name_len < size ); 100 0 : assert( headers[i].value_len < size ); 101 0 : } 102 3 : } else { 103 3 : FD_FUZZ_MUST_BE_COVERED; 104 3 : } 105 3 : } while(0); 106 : 107 3 : FD_FUZZ_MUST_BE_COVERED; 108 3 : return 0; 109 3 : }