aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer.c105
1 files changed, 63 insertions, 42 deletions
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index bb74a816a6..1e508e28a1 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -361,12 +361,15 @@ typedef struct call_state {
char *recv_status_details;
size_t recv_status_details_capacity;
int cancelled;
+ int pending_ops;
grpc_call_details call_details;
struct call_state *next;
struct call_state *prev;
} call_state;
+static call_state *g_active_call;
+
static call_state *new_call(call_state *sibling, call_state_type type) {
call_state *c = gpr_malloc(sizeof(*c));
memset(c, 0, sizeof(*c));
@@ -381,14 +384,15 @@ static call_state *new_call(call_state *sibling, call_state_type type) {
return c;
}
-static call_state *maybe_delete_call_state(call_state **active, call_state *call) {
+static call_state *maybe_delete_call_state(call_state *call) {
call_state *next = call->next;
if (call->call != NULL) return next;
+ if (call->pending_ops != 0) return next;
- if (call == *active) {
- *active = call->next;
- GPR_ASSERT(call != *active);
+ if (call == g_active_call) {
+ g_active_call = call->next;
+ GPR_ASSERT(call != g_active_call);
}
call->prev->next = call->next;
@@ -402,10 +406,28 @@ static call_state *maybe_delete_call_state(call_state **active, call_state *call
return next;
}
-static call_state *destroy_call(call_state **active, call_state *call) {
+static call_state *destroy_call(call_state *call) {
grpc_call_destroy(call->call);
call->call = NULL;
- return maybe_delete_call_state(active, call);
+ return maybe_delete_call_state(call);
+}
+
+static void finished_request_call(void *csp, bool success) {
+ call_state *cs = csp;
+ GPR_ASSERT(cs->pending_ops > 0);
+ --cs->pending_ops;
+ if (success) {
+ GPR_ASSERT(cs->call != NULL);
+ cs->type = SERVER;
+ } else {
+ maybe_delete_call_state(cs);
+ }
+}
+
+static void finished_batch(void *csp, bool success) {
+ call_state *cs = csp;
+ --cs->pending_ops;
+ maybe_delete_call_state(cs);
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
@@ -424,14 +446,13 @@ 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;
- call_state *active_call = new_call(NULL, ROOT);
+ g_active_call = new_call(NULL, ROOT);
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_ops > 0 || active_call->type != ROOT || active_call->next != active_call) {
+ pending_channel_watches > 0 || pending_pings > 0 || g_active_call->type != ROOT || g_active_call->next != g_active_call) {
if (is_eof(&inp)) {
if (g_channel != NULL) {
grpc_channel_destroy(g_channel);
@@ -449,14 +470,14 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
g_server = NULL;
}
}
- call_state *s = active_call;
+ call_state *s = g_active_call;
do {
if (s->type != PENDING_SERVER && s->call != NULL) {
- s = destroy_call(&active_call, s);
+ s = destroy_call(s);
} else {
s = s->next;
}
- } while (s != active_call);
+ } while (s != g_active_call);
g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN));
}
@@ -606,12 +627,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
bool ok = true;
if (g_channel == NULL) ok = false;
grpc_call *parent_call = NULL;
- if (active_call->type != ROOT) {
- if (active_call->call == NULL || active_call->type == CLIENT) {
+ if (g_active_call->type != ROOT) {
+ if (g_active_call->call == NULL || g_active_call->type == CLIENT) {
end(&inp);
break;
}
- parent_call = active_call->call;
+ parent_call = g_active_call->call;
}
uint32_t propagation_mask = read_uint32(&inp);
char *method = read_string(&inp);
@@ -621,7 +642,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
if (ok) {
- call_state *cs = new_call(active_call, CLIENT);
+ call_state *cs = new_call(g_active_call, CLIENT);
cs->call =
grpc_channel_create_call(g_channel, parent_call, propagation_mask,
cq, method, host, deadline, NULL);
@@ -634,13 +655,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
// switch the 'current' call
case 11: {
- active_call = active_call->next;
+ g_active_call = g_active_call->next;
break;
}
// queue some ops on a call
case 12: {
- if (active_call->type == PENDING_SERVER || active_call->type == ROOT ||
- active_call->call == NULL) {
+ if (g_active_call->type == PENDING_SERVER || g_active_call->type == ROOT ||
+ g_active_call->call == NULL) {
end(&inp);
break;
}
@@ -686,35 +707,35 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
case GRPC_OP_RECV_INITIAL_METADATA:
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata =
- &active_call->recv_initial_metadata;
+ &g_active_call->recv_initial_metadata;
break;
case GRPC_OP_RECV_MESSAGE:
op->op = GRPC_OP_RECV_MESSAGE;
- op->data.recv_message = &active_call->recv_message;
+ op->data.recv_message = &g_active_call->recv_message;
break;
case GRPC_OP_RECV_STATUS_ON_CLIENT:
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
- op->data.recv_status_on_client.status = &active_call->status;
+ op->data.recv_status_on_client.status = &g_active_call->status;
op->data.recv_status_on_client.trailing_metadata =
- &active_call->recv_trailing_metadata;
+ &g_active_call->recv_trailing_metadata;
op->data.recv_status_on_client.status_details =
- &active_call->recv_status_details;
+ &g_active_call->recv_status_details;
op->data.recv_status_on_client.status_details_capacity =
- &active_call->recv_status_details_capacity;
+ &g_active_call->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 = &active_call->cancelled;
+ op->data.recv_close_on_server.cancelled = &g_active_call->cancelled;
break;
}
op->reserved = NULL;
op->flags = read_uint32(&inp);
}
if (ok) {
- validator *v = create_validator(decrement, &pending_ops);
- pending_ops++;
+ validator *v = create_validator(finished_batch, g_active_call);
+ g_active_call->pending_ops++;
grpc_call_error error =
- grpc_call_start_batch(active_call->call, ops, num_ops, v, NULL);
+ grpc_call_start_batch(g_active_call->call, ops, num_ops, v, NULL);
if (error != GRPC_CALL_OK) {
v->validate(v->arg, false);
gpr_free(v);
@@ -766,8 +787,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
// cancel current call
case 13: {
- if (active_call->type != ROOT && active_call->call != NULL) {
- grpc_call_cancel(active_call->call, NULL);
+ if (g_active_call->type != ROOT && g_active_call->call != NULL) {
+ grpc_call_cancel(g_active_call->call, NULL);
} else {
end(&inp);
}
@@ -775,8 +796,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
// get a calls peer
case 14: {
- if (active_call->type != ROOT && active_call->call != NULL) {
- free_non_null(grpc_call_get_peer(active_call->call));
+ if (g_active_call->type != ROOT && g_active_call->call != NULL) {
+ free_non_null(grpc_call_get_peer(g_active_call->call));
} else {
end(&inp);
}
@@ -822,9 +843,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
end(&inp);
break;
}
- call_state *cs = new_call(active_call, PENDING_SERVER);
- pending_ops++;
- validator *v = create_validator(decrement, &pending_ops);
+ call_state *cs = new_call(g_active_call, PENDING_SERVER);
+ cs->pending_ops++;
+ validator *v = create_validator(finished_request_call, cs);
grpc_call_error error =
grpc_server_request_call(g_server, &cs->call, &cs->call_details,
&cs->recv_initial_metadata, cq, cq, v);
@@ -836,9 +857,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
// destroy a call
case 20: {
- if (active_call->type != ROOT && active_call->type != PENDING_SERVER &&
- active_call->call != NULL) {
- destroy_call(&active_call, active_call);
+ if (g_active_call->type != ROOT && g_active_call->type != PENDING_SERVER &&
+ g_active_call->call != NULL) {
+ destroy_call(g_active_call);
} else {
end(&inp);
}
@@ -849,9 +870,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
GPR_ASSERT(g_channel == NULL);
GPR_ASSERT(g_server == NULL);
- GPR_ASSERT(active_call->type == ROOT);
- GPR_ASSERT(active_call->next == active_call);
- gpr_free(active_call);
+ GPR_ASSERT(g_active_call->type == ROOT);
+ GPR_ASSERT(g_active_call->next == g_active_call);
+ gpr_free(g_active_call);
grpc_completion_queue_shutdown(cq);
GPR_ASSERT(