|
|
|
@ -82,6 +82,14 @@ static char *read_string(input_stream *inp) { |
|
|
|
|
return str; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void read_buffer(input_stream *inp, char **buffer, size_t *length) { |
|
|
|
|
*length = next_byte(inp); |
|
|
|
|
*buffer = gpr_malloc(*length); |
|
|
|
|
for (size_t i = 0; i < *length; i++) { |
|
|
|
|
(*buffer)[i] = (char)next_byte(inp); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static uint32_t read_uint32(input_stream *inp) { |
|
|
|
|
uint8_t b = next_byte(inp); |
|
|
|
|
uint32_t x = b & 0x7f; |
|
|
|
@ -106,6 +114,23 @@ static uint32_t read_uint32(input_stream *inp) { |
|
|
|
|
return x; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static grpc_byte_buffer *read_message(input_stream *inp) { |
|
|
|
|
gpr_slice slice = gpr_slice_malloc(read_uint32(inp)); |
|
|
|
|
memset(GPR_SLICE_START_PTR(slice), 0, GPR_SLICE_LENGTH(slice)); |
|
|
|
|
return grpc_raw_byte_buffer_create(&slice, 1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void read_metadata(input_stream *inp, size_t *count, grpc_metadata **metadata) { |
|
|
|
|
*count = next_byte(inp); |
|
|
|
|
*metadata = gpr_malloc(*count * sizeof(**metadata)); |
|
|
|
|
memset(*metadata, 0, *count * sizeof(**metadata)); |
|
|
|
|
for (size_t i = 0; i < *count; i++) { |
|
|
|
|
(*metadata)[i].key = read_string(inp); |
|
|
|
|
read_buffer(inp, (char**)&(*metadata[i]).value, &(*metadata[i]).value_length); |
|
|
|
|
(*metadata)[i].flags = read_uint32(inp); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int read_int(input_stream *inp) { return (int)read_uint32(inp); } |
|
|
|
|
|
|
|
|
|
static grpc_channel_args *read_args(input_stream *inp) { |
|
|
|
@ -304,7 +329,13 @@ static void free_non_null(void *p) { |
|
|
|
|
typedef struct call_state { |
|
|
|
|
grpc_call *client; |
|
|
|
|
grpc_call *server; |
|
|
|
|
grpc_byte_buffer *recv_message[2]; |
|
|
|
|
grpc_status_code status; |
|
|
|
|
grpc_metadata_array recv_initial_metadata; |
|
|
|
|
grpc_metadata_array recv_trailing_metadata; |
|
|
|
|
char *recv_status_details; |
|
|
|
|
size_t recv_status_details_capacity; |
|
|
|
|
int cancelled; |
|
|
|
|
} call_state; |
|
|
|
|
|
|
|
|
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
@ -323,6 +354,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
int pending_server_shutdowns = 0; |
|
|
|
|
int pending_channel_watches = 0; |
|
|
|
|
int pending_pings = 0; |
|
|
|
|
int pending_ops = 0; |
|
|
|
|
|
|
|
|
|
#define MAX_CALLS 16 |
|
|
|
|
call_state calls[MAX_CALLS]; |
|
|
|
@ -332,7 +364,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_pings > 0) { |
|
|
|
|
pending_channel_watches > 0 || pending_pings > 0 || pending_ops > 0) { |
|
|
|
|
if (is_eof(&inp)) { |
|
|
|
|
if (g_channel != NULL) { |
|
|
|
|
grpc_channel_destroy(g_channel); |
|
|
|
@ -549,15 +581,16 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
if (ok && !on_server && calls[0].client == NULL) { |
|
|
|
|
ok = false; |
|
|
|
|
} |
|
|
|
|
for (size_t i = 0; i < num_ops; i++) { |
|
|
|
|
grpc_op *op = &ops[i]; |
|
|
|
|
size_t i; |
|
|
|
|
grpc_op *op; |
|
|
|
|
for (i = 0; i < num_ops; i++) { |
|
|
|
|
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; |
|
|
|
@ -565,12 +598,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
op->op = GRPC_OP_SEND_INITIAL_METADATA; |
|
|
|
|
op->data.send_message = read_message(&inp); |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_CLOSE_FROM_CLIENT: |
|
|
|
|
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; |
|
|
|
|
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); |
|
|
|
|
op->data.send_status_from_server.status = next_byte(&inp); |
|
|
|
|
op->data.send_status_from_server.status_details = read_string(&inp); |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_INITIAL_METADATA: |
|
|
|
|
op->op = GRPC_OP_RECV_INITIAL_METADATA; |
|
|
|
@ -598,12 +636,39 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
op->reserved = NULL; |
|
|
|
|
op->flags = read_uint32(&inp); |
|
|
|
|
if (ok) { |
|
|
|
|
validator *v = create_validator(decrement, &pending_ops); |
|
|
|
|
pending_ops++; |
|
|
|
|
grpc_call_error error = grpc_call_start_batch( |
|
|
|
|
on_server ? calls[0].server : calls[0].client, ops, num_ops, |
|
|
|
|
tag, NULL); |
|
|
|
|
v, NULL); |
|
|
|
|
if (error != GRPC_CALL_OK) { |
|
|
|
|
v->validate(v->arg, false); |
|
|
|
|
gpr_free(v); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < num_ops; i++) { |
|
|
|
|
op = &ops[i]; |
|
|
|
|
switch (op->op) { |
|
|
|
|
case GRPC_OP_SEND_INITIAL_METADATA: |
|
|
|
|
gpr_free(op->data.send_initial_metadata.metadata); |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_MESSAGE: |
|
|
|
|
grpc_byte_buffer_destroy(op->data.send_message); |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_STATUS_FROM_SERVER: |
|
|
|
|
gpr_free(op->data.send_status_from_server.trailing_metadata); |
|
|
|
|
gpr_free((void*)op->data.send_status_from_server.status_details); |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_CLOSE_FROM_CLIENT: |
|
|
|
|
case GRPC_OP_RECV_INITIAL_METADATA: |
|
|
|
|
case GRPC_OP_RECV_MESSAGE: |
|
|
|
|
case GRPC_OP_RECV_STATUS_ON_CLIENT: |
|
|
|
|
case GRPC_OP_RECV_CLOSE_ON_SERVER: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -619,7 +684,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
// cancel current call on server
|
|
|
|
|
case 14: { |
|
|
|
|
if (num_calls > 0 && calls[0].server) { |
|
|
|
|
grpc_call_cancel(calls[0].server, NULL) |
|
|
|
|
grpc_call_cancel(calls[0].server, NULL); |
|
|
|
|
} else { |
|
|
|
|
end(&inp); |
|
|
|
|
} |
|
|
|
@ -676,13 +741,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
|
|
|
|
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, ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|