Line data Source code
1 : #if !FD_HAS_HOSTED
2 : #error "This target requires FD_HAS_HOSTED"
3 : #endif
4 :
5 : #include <stdlib.h>
6 : #include <stddef.h>
7 : #include <string.h>
8 : #include <stdio.h>
9 :
10 : #include "fd_grpc_codec.h"
11 : #include "../h2/fd_h2_rbuf.h"
12 :
13 : int
14 : LLVMFuzzerInitialize( int *argc,
15 12 : char ***argv ) {
16 : /* Set up shell without signal handlers */
17 12 : putenv( "FD_LOG_BACKTRACE=0" );
18 12 : fd_boot( argc, argv );
19 12 : (void) atexit( fd_halt );
20 12 : fd_log_level_core_set( 1 ); /* crash on info log */
21 12 : return 0;
22 12 : }
23 :
24 : static void
25 : expect_hdr( fd_hpack_rd_t *hpack_rd, fd_h2_hdr_t *hdr, uchar **scratch,
26 0 : const char *expected_name, const char *expected_value ) {
27 0 : FD_TEST( !fd_hpack_rd_done( hpack_rd ));
28 0 : FD_TEST( !fd_hpack_rd_next( hpack_rd, hdr, scratch, 0UL ));
29 0 : ulong name_len = strlen( expected_name );
30 0 : ulong value_len = strlen( expected_value );
31 0 : FD_TEST( hdr->name_len==name_len );
32 0 : FD_TEST( fd_memeq( hdr->name, expected_name, name_len ));
33 0 : FD_TEST( hdr->value_len==value_len );
34 0 : FD_TEST( fd_memeq( hdr->value, expected_value, value_len ));
35 0 : }
36 :
37 : int
38 : LLVMFuzzerTestOneInput( uchar const *data,
39 : ulong size ) {
40 : char host[256], path[256], bearer_auth[256], version[256];
41 : char host_port[512], user_agent[512];
42 : ulong minimum_len = sizeof( ushort )+ // port
43 : sizeof( char )+ // https
44 : 4UL; // lengths of strings
45 : if( FD_UNLIKELY( size < minimum_len )) {
46 : return 1;
47 : }
48 : ulong remaining = size-minimum_len;
49 :
50 : uchar host_len = data[ 0 ];
51 : uchar path_len = data[ 1 ];
52 : uchar bearer_auth_len = data[ 2 ];
53 : uchar version_len = data[ 3 ];
54 : uchar https = data[ 4 ];
55 : ushort port = (ushort)(data[ 5 ] << 8 | data[ 6 ]);
56 : if( FD_UNLIKELY( (ulong)host_len+(ulong)path_len+(ulong)bearer_auth_len+(ulong)version_len>remaining )) {
57 : return 1;
58 : }
59 : const char *content = (const char *) (data+minimum_len);
60 : const char *p = content;
61 :
62 : strncpy( host, p, host_len );
63 : host[ host_len ] = '\0';
64 : p += host_len;
65 :
66 : strncpy( path, p, path_len );
67 : path[ path_len ] = '\0';
68 : p += path_len;
69 :
70 : strncpy( bearer_auth, p, bearer_auth_len );
71 : bearer_auth[ bearer_auth_len ] = '\0';
72 : p += bearer_auth_len;
73 :
74 : strncpy( version, p, version_len );
75 : version[ version_len ] = '\0';
76 :
77 : /* update length if there is a null byte in the middle */
78 : host_len = (uchar)strlen( host );
79 : path_len = (uchar)strlen( path );
80 : bearer_auth_len = (uchar)strlen( bearer_auth );
81 : version_len = (uchar)strlen( version );
82 : if( FD_UNLIKELY((host_len==0) | (path_len==0) | (bearer_auth_len==0) | (version_len==0))) {
83 : return 1;
84 : }
85 :
86 : snprintf( host_port, sizeof(host_port), "%s:%d", host, port );
87 :
88 : snprintf( user_agent, sizeof(user_agent), "grpc-firedancer/%s", version );
89 :
90 : fd_grpc_req_hdrs_t req = {
91 : .host = host,
92 : .host_len = host_len,
93 : .port = port,
94 : .path = path,
95 : .path_len = path_len,
96 : .https = (uint)https%2,
97 : .bearer_auth = bearer_auth,
98 : .bearer_auth_len = bearer_auth_len,
99 : };
100 : uchar buf[2048];
101 : fd_h2_rbuf_t rbuf_tx[1];
102 : fd_h2_rbuf_init( rbuf_tx, buf, sizeof(buf));
103 : FD_TEST( fd_grpc_h2_gen_request_hdrs( &req, rbuf_tx, version, version_len ) == 1 );
104 : FD_TEST((rbuf_tx->lo_off == 0) & (rbuf_tx->lo == buf));
105 :
106 : fd_hpack_rd_t hpack_rd[1];
107 : fd_hpack_rd_init( hpack_rd, buf, rbuf_tx->hi_off );
108 : fd_h2_hdr_t hdr[1];
109 : uchar *scratch = NULL;
110 : expect_hdr( hpack_rd, hdr, &scratch, ":method", "POST" );
111 : expect_hdr( hpack_rd, hdr, &scratch, ":scheme", "https" );
112 : expect_hdr( hpack_rd, hdr, &scratch, ":path", path );
113 : expect_hdr( hpack_rd, hdr, &scratch, ":authority", host_port );
114 : expect_hdr( hpack_rd, hdr, &scratch, "te", "trailers" );
115 : expect_hdr( hpack_rd, hdr, &scratch, "content-type", "application/grpc+proto" );
116 : expect_hdr( hpack_rd, hdr, &scratch, "user-agent", user_agent );
117 : FD_TEST( !fd_hpack_rd_done( hpack_rd ));
118 : FD_TEST( !fd_hpack_rd_next( hpack_rd, hdr, &scratch, 0UL ));
119 : FD_TEST( hdr->name_len == 13 );
120 : FD_TEST( fd_memeq( hdr->name, "authorization", 13UL ));
121 : FD_TEST( hdr->value_len == 7+req.bearer_auth_len );
122 : FD_TEST( fd_memeq( hdr->value, "Bearer ", 7UL ));
123 : FD_TEST( fd_memeq( hdr->value+7, req.bearer_auth, req.bearer_auth_len ));
124 : FD_TEST( fd_hpack_rd_done( hpack_rd ));
125 :
126 : return 0;
127 : }
|