Fix inf loop

pull/6160/head
Craig Tiller 9 years ago
parent ffae017694
commit 6321cf2a3c
  1. 105
      test/core/end2end/fuzzers/api_fuzzer.c

@ -361,12 +361,15 @@ typedef struct call_state {
char *recv_status_details; char *recv_status_details;
size_t recv_status_details_capacity; size_t recv_status_details_capacity;
int cancelled; int cancelled;
int pending_ops;
grpc_call_details call_details; grpc_call_details call_details;
struct call_state *next; struct call_state *next;
struct call_state *prev; struct call_state *prev;
} call_state; } call_state;
static call_state *g_active_call;
static call_state *new_call(call_state *sibling, call_state_type type) { static call_state *new_call(call_state *sibling, call_state_type type) {
call_state *c = gpr_malloc(sizeof(*c)); call_state *c = gpr_malloc(sizeof(*c));
memset(c, 0, 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; 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; call_state *next = call->next;
if (call->call != NULL) return next; if (call->call != NULL) return next;
if (call->pending_ops != 0) return next;
if (call == *active) { if (call == g_active_call) {
*active = call->next; g_active_call = call->next;
GPR_ASSERT(call != *active); GPR_ASSERT(call != g_active_call);
} }
call->prev->next = call->next; call->prev->next = call->next;
@ -402,10 +406,28 @@ static call_state *maybe_delete_call_state(call_state **active, call_state *call
return next; 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); grpc_call_destroy(call->call);
call->call = NULL; 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) { 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_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;
call_state *active_call = new_call(NULL, ROOT); g_active_call = new_call(NULL, ROOT);
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_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 (is_eof(&inp)) {
if (g_channel != NULL) { if (g_channel != NULL) {
grpc_channel_destroy(g_channel); grpc_channel_destroy(g_channel);
@ -449,14 +470,14 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
g_server = NULL; g_server = NULL;
} }
} }
call_state *s = active_call; call_state *s = g_active_call;
do { do {
if (s->type != PENDING_SERVER && s->call != NULL) { if (s->type != PENDING_SERVER && s->call != NULL) {
s = destroy_call(&active_call, s); s = destroy_call(s);
} else { } else {
s = s->next; 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)); 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; bool ok = true;
if (g_channel == NULL) ok = false; if (g_channel == NULL) ok = false;
grpc_call *parent_call = NULL; grpc_call *parent_call = NULL;
if (active_call->type != ROOT) { if (g_active_call->type != ROOT) {
if (active_call->call == NULL || active_call->type == CLIENT) { if (g_active_call->call == NULL || g_active_call->type == CLIENT) {
end(&inp); end(&inp);
break; break;
} }
parent_call = active_call->call; parent_call = g_active_call->call;
} }
uint32_t propagation_mask = read_uint32(&inp); uint32_t propagation_mask = read_uint32(&inp);
char *method = read_string(&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)); gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
if (ok) { if (ok) {
call_state *cs = new_call(active_call, CLIENT); call_state *cs = new_call(g_active_call, CLIENT);
cs->call = cs->call =
grpc_channel_create_call(g_channel, parent_call, propagation_mask, grpc_channel_create_call(g_channel, parent_call, propagation_mask,
cq, method, host, deadline, NULL); cq, method, host, deadline, NULL);
@ -634,13 +655,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
} }
// switch the 'current' call // switch the 'current' call
case 11: { case 11: {
active_call = active_call->next; g_active_call = g_active_call->next;
break; break;
} }
// queue some ops on a call // queue some ops on a call
case 12: { case 12: {
if (active_call->type == PENDING_SERVER || active_call->type == ROOT || if (g_active_call->type == PENDING_SERVER || g_active_call->type == ROOT ||
active_call->call == NULL) { g_active_call->call == NULL) {
end(&inp); end(&inp);
break; break;
} }
@ -686,35 +707,35 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
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;
op->data.recv_initial_metadata = op->data.recv_initial_metadata =
&active_call->recv_initial_metadata; &g_active_call->recv_initial_metadata;
break; break;
case GRPC_OP_RECV_MESSAGE: case GRPC_OP_RECV_MESSAGE:
op->op = 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; break;
case GRPC_OP_RECV_STATUS_ON_CLIENT: case GRPC_OP_RECV_STATUS_ON_CLIENT:
op->op = 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 = 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 = 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 = op->data.recv_status_on_client.status_details_capacity =
&active_call->recv_status_details_capacity; &g_active_call->recv_status_details_capacity;
break; break;
case GRPC_OP_RECV_CLOSE_ON_SERVER: case GRPC_OP_RECV_CLOSE_ON_SERVER:
op->op = 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; break;
} }
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); validator *v = create_validator(finished_batch, g_active_call);
pending_ops++; g_active_call->pending_ops++;
grpc_call_error error = 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) { if (error != GRPC_CALL_OK) {
v->validate(v->arg, false); v->validate(v->arg, false);
gpr_free(v); gpr_free(v);
@ -766,8 +787,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
} }
// cancel current call // cancel current call
case 13: { case 13: {
if (active_call->type != ROOT && active_call->call != NULL) { if (g_active_call->type != ROOT && g_active_call->call != NULL) {
grpc_call_cancel(active_call->call, NULL); grpc_call_cancel(g_active_call->call, NULL);
} else { } else {
end(&inp); end(&inp);
} }
@ -775,8 +796,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
} }
// get a calls peer // get a calls peer
case 14: { case 14: {
if (active_call->type != ROOT && active_call->call != NULL) { if (g_active_call->type != ROOT && g_active_call->call != NULL) {
free_non_null(grpc_call_get_peer(active_call->call)); free_non_null(grpc_call_get_peer(g_active_call->call));
} else { } else {
end(&inp); end(&inp);
} }
@ -822,9 +843,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
end(&inp); end(&inp);
break; break;
} }
call_state *cs = new_call(active_call, PENDING_SERVER); call_state *cs = new_call(g_active_call, PENDING_SERVER);
pending_ops++; cs->pending_ops++;
validator *v = create_validator(decrement, &pending_ops); validator *v = create_validator(finished_request_call, cs);
grpc_call_error error = grpc_call_error error =
grpc_server_request_call(g_server, &cs->call, &cs->call_details, grpc_server_request_call(g_server, &cs->call, &cs->call_details,
&cs->recv_initial_metadata, cq, cq, v); &cs->recv_initial_metadata, cq, cq, v);
@ -836,9 +857,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
} }
// destroy a call // destroy a call
case 20: { case 20: {
if (active_call->type != ROOT && active_call->type != PENDING_SERVER && if (g_active_call->type != ROOT && g_active_call->type != PENDING_SERVER &&
active_call->call != NULL) { g_active_call->call != NULL) {
destroy_call(&active_call, active_call); destroy_call(g_active_call);
} else { } else {
end(&inp); end(&inp);
} }
@ -849,9 +870,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
GPR_ASSERT(g_channel == NULL); GPR_ASSERT(g_channel == NULL);
GPR_ASSERT(g_server == NULL); GPR_ASSERT(g_server == NULL);
GPR_ASSERT(active_call->type == ROOT); GPR_ASSERT(g_active_call->type == ROOT);
GPR_ASSERT(active_call->next == active_call); GPR_ASSERT(g_active_call->next == g_active_call);
gpr_free(active_call); gpr_free(g_active_call);
grpc_completion_queue_shutdown(cq); grpc_completion_queue_shutdown(cq);
GPR_ASSERT( GPR_ASSERT(

Loading…
Cancel
Save