|
|
|
@ -272,6 +272,8 @@ static void assert_success_and_decrement(void *counter, bool success) { |
|
|
|
|
--*(int *)counter; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void decrement(void *counter, bool success) { --*(int *)counter; } |
|
|
|
|
|
|
|
|
|
typedef struct connectivity_watch { |
|
|
|
|
int *counter; |
|
|
|
|
gpr_timespec deadline; |
|
|
|
@ -294,9 +296,15 @@ static void validate_connectivity_watch(void *p, bool success) { |
|
|
|
|
gpr_free(w); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void free_non_null(void *p) { |
|
|
|
|
GPR_ASSERT(p != NULL); |
|
|
|
|
gpr_free(p); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
typedef struct call_state { |
|
|
|
|
grpc_call *client; |
|
|
|
|
grpc_call *server; |
|
|
|
|
grpc_metadata_array recv_initial_metadata; |
|
|
|
|
} call_state; |
|
|
|
|
|
|
|
|
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
@ -314,6 +322,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
bool server_shutdown = false; |
|
|
|
|
int pending_server_shutdowns = 0; |
|
|
|
|
int pending_channel_watches = 0; |
|
|
|
|
int pending_pings = 0; |
|
|
|
|
|
|
|
|
|
#define MAX_CALLS 16 |
|
|
|
|
call_state calls[MAX_CALLS]; |
|
|
|
@ -323,7 +332,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
grpc_completion_queue *cq = grpc_completion_queue_create(NULL); |
|
|
|
|
|
|
|
|
|
while (!is_eof(&inp) || g_channel != NULL || g_server != NULL || |
|
|
|
|
pending_channel_watches > 0) { |
|
|
|
|
pending_channel_watches > 0 || pending_pings > 0) { |
|
|
|
|
if (is_eof(&inp)) { |
|
|
|
|
if (g_channel != NULL) { |
|
|
|
|
grpc_channel_destroy(g_channel); |
|
|
|
@ -525,6 +534,155 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// queue some ops on a call
|
|
|
|
|
case 12: { |
|
|
|
|
size_t num_ops = next_byte(&inp); |
|
|
|
|
grpc_op *ops = gpr_malloc(sizeof(grpc_op) * num_ops); |
|
|
|
|
bool ok = num_calls > 0; |
|
|
|
|
uint8_t on_server = next_byte(&inp); |
|
|
|
|
if (on_server != 0 && on_server != 1) { |
|
|
|
|
ok = false; |
|
|
|
|
} |
|
|
|
|
if (ok && on_server && calls[0].server == NULL) { |
|
|
|
|
ok = false; |
|
|
|
|
} |
|
|
|
|
if (ok && !on_server && calls[0].client == NULL) { |
|
|
|
|
ok = false; |
|
|
|
|
} |
|
|
|
|
for (size_t i = 0; i < num_ops; i++) { |
|
|
|
|
grpc_op *op = &ops[i]; |
|
|
|
|
switch (next_byte(&inp)) { |
|
|
|
|
default: |
|
|
|
|
ok = false; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_INITIAL_METADATA: |
|
|
|
|
op->op = GRPC_OP_SEND_INITIAL_METADATA; |
|
|
|
|
op->data.send_initial_metadata.count = next_byte(&inp); |
|
|
|
|
read_metadata(&inp, &op->data.send_initial_metadata.count, |
|
|
|
|
&op->data.send_initial_metadata.metadata); |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_MESSAGE: |
|
|
|
|
op->op = GRPC_OP_SEND_INITIAL_METADATA; |
|
|
|
|
op->data.send_message = read_message(&inp); |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_STATUS_FROM_SERVER: |
|
|
|
|
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; |
|
|
|
|
read_metadata( |
|
|
|
|
&inp, |
|
|
|
|
&op->data.send_status_from_server.trailing_metadata_count, |
|
|
|
|
&op->data.send_status_from_server.trailing_metadata); |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_INITIAL_METADATA: |
|
|
|
|
op->op = GRPC_OP_RECV_INITIAL_METADATA; |
|
|
|
|
op->data.recv_initial_metadata = &calls[0].recv_initial_metadata; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_MESSAGE: |
|
|
|
|
op->op = GRPC_OP_RECV_MESSAGE; |
|
|
|
|
op->data.recv_message = &calls[0].recv_message[on_server]; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_STATUS_ON_CLIENT: |
|
|
|
|
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; |
|
|
|
|
op->data.recv_status_on_client.status = &calls[0].status; |
|
|
|
|
op->data.recv_status_on_client.trailing_metadata = |
|
|
|
|
&calls[0].recv_trailing_metadata; |
|
|
|
|
op->data.recv_status_on_client.status_details = |
|
|
|
|
&calls[0].recv_status_details; |
|
|
|
|
op->data.recv_status_on_client.status_details_capacity = |
|
|
|
|
&calls[0].recv_status_details_capacity; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_CLOSE_ON_SERVER: |
|
|
|
|
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; |
|
|
|
|
op->data.recv_close_on_server.cancelled = &calls[0].cancelled; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op->flags = read_uint32(&inp); |
|
|
|
|
if (ok) { |
|
|
|
|
grpc_call_error error = grpc_call_start_batch( |
|
|
|
|
on_server ? calls[0].server : calls[0].client, ops, num_ops, |
|
|
|
|
tag, NULL); |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// cancel current call on client
|
|
|
|
|
case 13: { |
|
|
|
|
if (num_calls > 0 && calls[0].client) { |
|
|
|
|
grpc_call_cancel(calls[0].client, NULL); |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// cancel current call on server
|
|
|
|
|
case 14: { |
|
|
|
|
if (num_calls > 0 && calls[0].server) { |
|
|
|
|
grpc_call_cancel(calls[0].server, NULL) |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// get a calls peer on client
|
|
|
|
|
case 15: { |
|
|
|
|
if (num_calls > 0 && calls[0].client) { |
|
|
|
|
free_non_null(grpc_call_get_peer(calls[0].client)); |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// get a calls peer on server
|
|
|
|
|
case 16: { |
|
|
|
|
if (num_calls > 0 && calls[0].server) { |
|
|
|
|
free_non_null(grpc_call_get_peer(calls[0].server)); |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// get a channels target
|
|
|
|
|
case 17: { |
|
|
|
|
if (g_channel != NULL) { |
|
|
|
|
free_non_null(grpc_channel_get_target(g_channel)); |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// send a ping on a channel
|
|
|
|
|
case 18: { |
|
|
|
|
if (g_channel != NULL) { |
|
|
|
|
grpc_channel_ping(g_channel, cq, |
|
|
|
|
create_validator(decrement, &pending_pings), NULL); |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// enable a tracer
|
|
|
|
|
case 19: { |
|
|
|
|
char *tracer = read_string(&inp); |
|
|
|
|
grpc_tracer_set_enabled(tracer, 1); |
|
|
|
|
gpr_free(tracer); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// disable a tracer
|
|
|
|
|
case 20: { |
|
|
|
|
char *tracer = read_string(&inp); |
|
|
|
|
grpc_tracer_set_enabled(tracer, 0); |
|
|
|
|
gpr_free(tracer); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// create an alarm
|
|
|
|
|
case 21: { |
|
|
|
|
gpr_timespec deadline = |
|
|
|
|
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), |
|
|
|
|
gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); |
|
|
|
|
grpc_alarm *alarm = grpc_alarm_create(cq, ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|