diff options
author | Craig Tiller <ctiller@google.com> | 2016-04-15 13:07:54 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2016-04-15 13:07:54 -0700 |
commit | ba0d6ac79a0b937ee41d9d9c81547af2ebc78302 (patch) | |
tree | 97a5480405cae2c9f07409385035872830855a9f /test/core | |
parent | b91fe568007ede00f2d1b3530e4ba04c2d84f188 (diff) |
First pass client call fuzzing
Diffstat (limited to 'test/core')
-rw-r--r-- | test/core/end2end/fuzzers/api_fuzzer.c | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c index c74783bee4..cc98e02529 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.c +++ b/test/core/end2end/fuzzers/api_fuzzer.c @@ -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, ); - } } } |