diff options
-rw-r--r-- | test/core/end2end/fuzzers/api_fuzzer.c | 79 |
1 files changed, 76 insertions, 3 deletions
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c index e0dd717a8b..39d1d2ae20 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.c +++ b/test/core/end2end/fuzzers/api_fuzzer.c @@ -70,6 +70,8 @@ static uint8_t next_byte(input_stream *inp) { return *inp->cur++; } +static void end(input_stream *inp) { inp->cur = inp->end; } + static char *read_string(input_stream *inp) { size_t len = next_byte(inp); char *str = gpr_malloc(len + 1); @@ -292,6 +294,11 @@ static void validate_connectivity_watch(void *p, bool success) { gpr_free(w); } +typedef struct call_state { + grpc_call *client; + grpc_call *server; +} call_state; + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { grpc_test_only_set_metadata_hash_seed(0); if (squelch) gpr_set_log_function(dont_log); @@ -308,6 +315,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int pending_server_shutdowns = 0; int pending_channel_watches = 0; +#define MAX_CALLS 16 + call_state calls[MAX_CALLS]; + int num_calls = 0; + memset(calls, 0, sizeof(calls)); + grpc_completion_queue *cq = grpc_completion_queue_create(NULL); while (!is_eof(&inp) || g_channel != NULL || g_server != NULL || @@ -336,7 +348,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { switch (next_byte(&inp)) { // terminate on bad bytes default: - inp.cur = inp.end; + end(&inp); break; // tickle completion queue case 0: { @@ -375,6 +387,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { grpc_channel_args_destroy(args); gpr_free(target_uri); gpr_free(target); + } else { + end(&inp); } break; } @@ -383,6 +397,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (g_channel != NULL) { grpc_channel_destroy(g_channel); g_channel = NULL; + } else { + end(&inp); } break; } @@ -397,6 +413,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { grpc_server_start(g_server); server_shutdown = false; GPR_ASSERT(pending_server_shutdowns == 0); + } else { + end(&inp); } } // begin server shutdown @@ -407,6 +425,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { &pending_server_shutdowns)); pending_server_shutdowns++; server_shutdown = true; + } else { + end(&inp); } break; } @@ -414,6 +434,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case 6: { if (g_server != NULL && server_shutdown) { grpc_server_cancel_all_calls(g_server); + } else { + end(&inp); } break; } @@ -423,14 +445,22 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { pending_server_shutdowns == 0) { grpc_server_destroy(g_server); g_server = NULL; + } else { + end(&inp); } break; } // check connectivity case 8: { if (g_channel != NULL) { - grpc_channel_check_connectivity_state(g_channel, - next_byte(&inp) > 127); + uint8_t try_to_connect = next_byte(&inp); + if (try_to_connect == 0 || try_to_connect == 1) { + grpc_channel_check_connectivity_state(g_channel, try_to_connect); + } else { + end(&inp); + } + } else { + end(&inp); } break; } @@ -450,7 +480,50 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { deadline, &pending_channel_watches))); pending_channel_watches++; } + } else { + end(&inp); + } + break; + } + // create a call + case 10: { + bool ok = true; + if (g_channel == NULL) ok = false; + if (num_calls >= MAX_CALLS) ok = false; + grpc_call *parent_call = NULL; + uint8_t pcidx = next_byte(&inp); + if (pcidx > MAX_CALLS) + ok = false; + else if (pcidx < MAX_CALLS) { + parent_call = calls[pcidx].server; + if (parent_call == NULL) ok = false; + } + uint32_t propagation_mask = read_uint32(&inp); + char *method = read_string(&inp); + char *host = read_string(&inp); + gpr_timespec deadline = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); + + if (ok) { + GPR_ASSERT(calls[num_calls].client == NULL); + calls[num_calls].client = + grpc_channel_create_call(g_channel, parent_call, propagation_mask, + cq, method, host, deadline, NULL); + } else { + end(&inp); + } + break; + } + // switch the 'current' call + case 11: { + uint8_t new_current = next_byte(&inp); + if (new_current == 0 || new_current >= num_calls) { + end(&inp); + } else { + GPR_SWAP(call_state, calls[0], calls[new_current]); } + break; } } } |