Skip to content
Snippets Groups Projects
Commit ba0d6ac7 authored by Craig Tiller's avatar Craig Tiller
Browse files

First pass client call fuzzing

parent b91fe568
No related branches found
No related tags found
No related merge requests found
...@@ -82,6 +82,14 @@ static char *read_string(input_stream *inp) { ...@@ -82,6 +82,14 @@ static char *read_string(input_stream *inp) {
return str; 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) { static uint32_t read_uint32(input_stream *inp) {
uint8_t b = next_byte(inp); uint8_t b = next_byte(inp);
uint32_t x = b & 0x7f; uint32_t x = b & 0x7f;
...@@ -106,6 +114,23 @@ static uint32_t read_uint32(input_stream *inp) { ...@@ -106,6 +114,23 @@ static uint32_t read_uint32(input_stream *inp) {
return x; 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 int read_int(input_stream *inp) { return (int)read_uint32(inp); }
static grpc_channel_args *read_args(input_stream *inp) { static grpc_channel_args *read_args(input_stream *inp) {
...@@ -304,7 +329,13 @@ static void free_non_null(void *p) { ...@@ -304,7 +329,13 @@ static void free_non_null(void *p) {
typedef struct call_state { typedef struct call_state {
grpc_call *client; grpc_call *client;
grpc_call *server; grpc_call *server;
grpc_byte_buffer *recv_message[2];
grpc_status_code status;
grpc_metadata_array recv_initial_metadata; 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; } call_state;
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
...@@ -323,6 +354,7 @@ 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_server_shutdowns = 0;
int pending_channel_watches = 0; int pending_channel_watches = 0;
int pending_pings = 0; int pending_pings = 0;
int pending_ops = 0;
#define MAX_CALLS 16 #define MAX_CALLS 16
call_state calls[MAX_CALLS]; call_state calls[MAX_CALLS];
...@@ -332,7 +364,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ...@@ -332,7 +364,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
grpc_completion_queue *cq = grpc_completion_queue_create(NULL); grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
while (!is_eof(&inp) || g_channel != NULL || g_server != 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 (is_eof(&inp)) {
if (g_channel != NULL) { if (g_channel != NULL) {
grpc_channel_destroy(g_channel); grpc_channel_destroy(g_channel);
...@@ -549,15 +581,16 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ...@@ -549,15 +581,16 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (ok && !on_server && calls[0].client == NULL) { if (ok && !on_server && calls[0].client == NULL) {
ok = false; ok = false;
} }
for (size_t i = 0; i < num_ops; i++) { size_t i;
grpc_op *op = &ops[i]; grpc_op *op;
for (i = 0; i < num_ops; i++) {
op = &ops[i];
switch (next_byte(&inp)) { switch (next_byte(&inp)) {
default: default:
ok = false; ok = false;
break; break;
case GRPC_OP_SEND_INITIAL_METADATA: case GRPC_OP_SEND_INITIAL_METADATA:
op->op = 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, read_metadata(&inp, &op->data.send_initial_metadata.count,
&op->data.send_initial_metadata.metadata); &op->data.send_initial_metadata.metadata);
break; break;
...@@ -565,12 +598,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ...@@ -565,12 +598,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
op->op = GRPC_OP_SEND_INITIAL_METADATA; op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_message = read_message(&inp); op->data.send_message = read_message(&inp);
break; break;
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
break;
case GRPC_OP_SEND_STATUS_FROM_SERVER: case GRPC_OP_SEND_STATUS_FROM_SERVER:
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
read_metadata( read_metadata(
&inp, &inp,
&op->data.send_status_from_server.trailing_metadata_count, &op->data.send_status_from_server.trailing_metadata_count,
&op->data.send_status_from_server.trailing_metadata); &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; break;
case GRPC_OP_RECV_INITIAL_METADATA: case GRPC_OP_RECV_INITIAL_METADATA:
op->op = 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) { ...@@ -598,12 +636,39 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
op->reserved = NULL; op->reserved = NULL;
op->flags = read_uint32(&inp); op->flags = read_uint32(&inp);
if (ok) { if (ok) {
validator *v = create_validator(decrement, &pending_ops);
pending_ops++;
grpc_call_error error = grpc_call_start_batch( grpc_call_error error = grpc_call_start_batch(
on_server ? calls[0].server : calls[0].client, ops, num_ops, 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 { } else {
end(&inp); 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; break;
} }
...@@ -619,7 +684,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ...@@ -619,7 +684,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// cancel current call on server // cancel current call on server
case 14: { case 14: {
if (num_calls > 0 && calls[0].server) { if (num_calls > 0 && calls[0].server) {
grpc_call_cancel(calls[0].server, NULL) grpc_call_cancel(calls[0].server, NULL);
} else { } else {
end(&inp); end(&inp);
} }
...@@ -676,13 +741,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ...@@ -676,13 +741,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
gpr_free(tracer); gpr_free(tracer);
break; 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, );
}
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment