1 /*
2 *
3 * Copyright 2016 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <string.h>
20
21 #include <grpc/grpc.h>
22 #include <grpc/grpc_security.h>
23 #include <grpc/support/alloc.h>
24 #include <grpc/support/log.h>
25 #include <grpc/support/string_util.h>
26
27 #include "src/core/ext/filters/client_channel/lb_policy_factory.h"
28 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
29 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
30 #include "src/core/lib/channel/channel_args.h"
31 #include "src/core/lib/gpr/env.h"
32 #include "src/core/lib/iomgr/executor.h"
33 #include "src/core/lib/iomgr/resolve_address.h"
34 #include "src/core/lib/iomgr/tcp_client.h"
35 #include "src/core/lib/iomgr/timer.h"
36 #include "src/core/lib/iomgr/timer_manager.h"
37 #include "src/core/lib/slice/slice_internal.h"
38 #include "src/core/lib/surface/server.h"
39 #include "src/core/lib/transport/metadata.h"
40 #include "test/core/end2end/data/ssl_test_data.h"
41 #include "test/core/util/fuzzer_util.h"
42 #include "test/core/util/passthru_endpoint.h"
43
44 using grpc_core::testing::grpc_fuzzer_get_next_byte;
45 using grpc_core::testing::grpc_fuzzer_get_next_string;
46 using grpc_core::testing::grpc_fuzzer_get_next_uint32;
47 using grpc_core::testing::input_stream;
48
49 ////////////////////////////////////////////////////////////////////////////////
50 // logging
51
52 bool squelch = true;
53 bool leak_check = true;
54
dont_log(gpr_log_func_args * args)55 static void dont_log(gpr_log_func_args* args) {}
56
57 ////////////////////////////////////////////////////////////////////////////////
58 // global state
59
60 static gpr_timespec g_now;
61 static grpc_server* g_server;
62 static grpc_channel* g_channel;
63 static grpc_resource_quota* g_resource_quota;
64
65 extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
66
now_impl(gpr_clock_type clock_type)67 static gpr_timespec now_impl(gpr_clock_type clock_type) {
68 GPR_ASSERT(clock_type != GPR_TIMESPAN);
69 gpr_timespec ts = g_now;
70 ts.clock_type = clock_type;
71 return ts;
72 }
73
end(input_stream * inp)74 static void end(input_stream* inp) { inp->cur = inp->end; }
75
read_buffer(input_stream * inp,char ** buffer,size_t * length,bool * special)76 static void read_buffer(input_stream* inp, char** buffer, size_t* length,
77 bool* special) {
78 *length = grpc_fuzzer_get_next_byte(inp);
79 if (*length == 255) {
80 if (special != nullptr) *special = true;
81 *length = grpc_fuzzer_get_next_byte(inp);
82 } else {
83 if (special != nullptr) *special = false;
84 }
85 *buffer = static_cast<char*>(gpr_malloc(*length));
86 for (size_t i = 0; i < *length; i++) {
87 (*buffer)[i] = static_cast<char>(grpc_fuzzer_get_next_byte(inp));
88 }
89 }
90
maybe_intern(grpc_slice s,bool intern)91 static grpc_slice maybe_intern(grpc_slice s, bool intern) {
92 grpc_slice r = intern ? grpc_slice_intern(s) : grpc_slice_ref(s);
93 grpc_slice_unref(s);
94 return r;
95 }
96
read_string_like_slice(input_stream * inp)97 static grpc_slice read_string_like_slice(input_stream* inp) {
98 bool special;
99 char* s = grpc_fuzzer_get_next_string(inp, &special);
100 grpc_slice r = maybe_intern(grpc_slice_from_copied_string(s), special);
101 gpr_free(s);
102 return r;
103 }
104
read_buffer_like_slice(input_stream * inp)105 static grpc_slice read_buffer_like_slice(input_stream* inp) {
106 char* buffer;
107 size_t length;
108 bool special;
109 read_buffer(inp, &buffer, &length, &special);
110 grpc_slice r =
111 maybe_intern(grpc_slice_from_copied_buffer(buffer, length), special);
112 gpr_free(buffer);
113 return r;
114 }
115
read_uint22(input_stream * inp)116 static uint32_t read_uint22(input_stream* inp) {
117 uint8_t b = grpc_fuzzer_get_next_byte(inp);
118 uint32_t x = b & 0x7f;
119 if (b & 0x80) {
120 x <<= 7;
121 b = grpc_fuzzer_get_next_byte(inp);
122 x |= b & 0x7f;
123 if (b & 0x80) {
124 x <<= 8;
125 x |= grpc_fuzzer_get_next_byte(inp);
126 }
127 }
128 return x;
129 }
130
read_message(input_stream * inp)131 static grpc_byte_buffer* read_message(input_stream* inp) {
132 grpc_slice slice = grpc_slice_malloc(read_uint22(inp));
133 memset(GRPC_SLICE_START_PTR(slice), 0, GRPC_SLICE_LENGTH(slice));
134 grpc_byte_buffer* out = grpc_raw_byte_buffer_create(&slice, 1);
135 grpc_slice_unref(slice);
136 return out;
137 }
138
read_int(input_stream * inp)139 static int read_int(input_stream* inp) {
140 return static_cast<int>(grpc_fuzzer_get_next_uint32(inp));
141 }
142
read_args(input_stream * inp)143 static grpc_channel_args* read_args(input_stream* inp) {
144 size_t n = grpc_fuzzer_get_next_byte(inp);
145 grpc_arg* args = static_cast<grpc_arg*>(gpr_malloc(sizeof(*args) * n));
146 for (size_t i = 0; i < n; i++) {
147 switch (grpc_fuzzer_get_next_byte(inp)) {
148 case 1:
149 args[i].type = GRPC_ARG_STRING;
150 args[i].key = grpc_fuzzer_get_next_string(inp, nullptr);
151 args[i].value.string = grpc_fuzzer_get_next_string(inp, nullptr);
152 break;
153 case 2:
154 args[i].type = GRPC_ARG_INTEGER;
155 args[i].key = grpc_fuzzer_get_next_string(inp, nullptr);
156 args[i].value.integer = read_int(inp);
157 break;
158 case 3:
159 args[i].type = GRPC_ARG_POINTER;
160 args[i].key = gpr_strdup(GRPC_ARG_RESOURCE_QUOTA);
161 args[i].value.pointer.vtable = grpc_resource_quota_arg_vtable();
162 args[i].value.pointer.p = g_resource_quota;
163 grpc_resource_quota_ref(g_resource_quota);
164 break;
165 default:
166 end(inp);
167 n = i;
168 break;
169 }
170 }
171 grpc_channel_args* a =
172 static_cast<grpc_channel_args*>(gpr_malloc(sizeof(*a)));
173 a->args = args;
174 a->num_args = n;
175 return a;
176 }
177
178 typedef struct cred_artifact_ctx {
179 int num_release;
180 char* release[3];
181 } cred_artifact_ctx;
182 #define CRED_ARTIFACT_CTX_INIT \
183 { \
184 0, { 0 } \
185 }
186
cred_artifact_ctx_finish(cred_artifact_ctx * ctx)187 static void cred_artifact_ctx_finish(cred_artifact_ctx* ctx) {
188 for (int i = 0; i < ctx->num_release; i++) {
189 gpr_free(ctx->release[i]);
190 }
191 }
192
read_cred_artifact(cred_artifact_ctx * ctx,input_stream * inp,const char ** builtins,size_t num_builtins)193 static const char* read_cred_artifact(cred_artifact_ctx* ctx, input_stream* inp,
194 const char** builtins,
195 size_t num_builtins) {
196 uint8_t b = grpc_fuzzer_get_next_byte(inp);
197 if (b == 0) return nullptr;
198 if (b == 1)
199 return ctx->release[ctx->num_release++] =
200 grpc_fuzzer_get_next_string(inp, nullptr);
201 if (b >= num_builtins + 1) {
202 end(inp);
203 return nullptr;
204 }
205 return builtins[b - 1];
206 }
207
read_ssl_channel_creds(input_stream * inp)208 static grpc_channel_credentials* read_ssl_channel_creds(input_stream* inp) {
209 cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT;
210 static const char* builtin_root_certs[] = {test_root_cert};
211 static const char* builtin_private_keys[] = {
212 test_server1_key, test_self_signed_client_key, test_signed_client_key};
213 static const char* builtin_cert_chains[] = {
214 test_server1_cert, test_self_signed_client_cert, test_signed_client_cert};
215 const char* root_certs = read_cred_artifact(
216 &ctx, inp, builtin_root_certs, GPR_ARRAY_SIZE(builtin_root_certs));
217 const char* private_key = read_cred_artifact(
218 &ctx, inp, builtin_private_keys, GPR_ARRAY_SIZE(builtin_private_keys));
219 const char* certs = read_cred_artifact(&ctx, inp, builtin_cert_chains,
220 GPR_ARRAY_SIZE(builtin_cert_chains));
221 grpc_ssl_pem_key_cert_pair key_cert_pair = {private_key, certs};
222 grpc_channel_credentials* creds = grpc_ssl_credentials_create(
223 root_certs,
224 private_key != nullptr && certs != nullptr ? &key_cert_pair : nullptr,
225 nullptr, nullptr);
226 cred_artifact_ctx_finish(&ctx);
227 return creds;
228 }
229
read_call_creds(input_stream * inp,int depth)230 static grpc_call_credentials* read_call_creds(input_stream* inp, int depth) {
231 if (depth > 64) {
232 // prevent creating infinitely deep call creds
233 end(inp);
234 return nullptr;
235 }
236 switch (grpc_fuzzer_get_next_byte(inp)) {
237 default:
238 end(inp);
239 return nullptr;
240 case 0:
241 return nullptr;
242 case 1: {
243 grpc_call_credentials* c1 = read_call_creds(inp, depth + 1);
244 grpc_call_credentials* c2 = read_call_creds(inp, depth + 1);
245 if (c1 != nullptr && c2 != nullptr) {
246 grpc_call_credentials* out =
247 grpc_composite_call_credentials_create(c1, c2, nullptr);
248 grpc_call_credentials_release(c1);
249 grpc_call_credentials_release(c2);
250 return out;
251 } else if (c1 != nullptr) {
252 return c1;
253 } else if (c2 != nullptr) {
254 return c2;
255 } else {
256 return nullptr;
257 }
258 GPR_UNREACHABLE_CODE(return nullptr);
259 }
260 case 2: {
261 cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT;
262 const char* access_token = read_cred_artifact(&ctx, inp, nullptr, 0);
263 grpc_call_credentials* out =
264 access_token == nullptr
265 ? nullptr
266 : grpc_access_token_credentials_create(access_token, nullptr);
267 cred_artifact_ctx_finish(&ctx);
268 return out;
269 }
270 case 3: {
271 cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT;
272 const char* auth_token = read_cred_artifact(&ctx, inp, nullptr, 0);
273 const char* auth_selector = read_cred_artifact(&ctx, inp, nullptr, 0);
274 grpc_call_credentials* out =
275 auth_token == nullptr || auth_selector == nullptr
276 ? nullptr
277 : grpc_google_iam_credentials_create(auth_token, auth_selector,
278 nullptr);
279 cred_artifact_ctx_finish(&ctx);
280 return out;
281 }
282 /* TODO(ctiller): more cred types here */
283 }
284 }
285
read_channel_creds(input_stream * inp)286 static grpc_channel_credentials* read_channel_creds(input_stream* inp) {
287 switch (grpc_fuzzer_get_next_byte(inp)) {
288 case 0:
289 return read_ssl_channel_creds(inp);
290 break;
291 case 1: {
292 grpc_channel_credentials* c1 = read_channel_creds(inp);
293 grpc_call_credentials* c2 = read_call_creds(inp, 0);
294 if (c1 != nullptr && c2 != nullptr) {
295 grpc_channel_credentials* out =
296 grpc_composite_channel_credentials_create(c1, c2, nullptr);
297 grpc_channel_credentials_release(c1);
298 grpc_call_credentials_release(c2);
299 return out;
300 } else if (c1) {
301 return c1;
302 } else if (c2) {
303 grpc_call_credentials_release(c2);
304 return nullptr;
305 } else {
306 return nullptr;
307 }
308 GPR_UNREACHABLE_CODE(return nullptr);
309 }
310 case 2:
311 return nullptr;
312 default:
313 end(inp);
314 return nullptr;
315 }
316 }
317
is_eof(input_stream * inp)318 static bool is_eof(input_stream* inp) { return inp->cur == inp->end; }
319
320 ////////////////////////////////////////////////////////////////////////////////
321 // dns resolution
322
323 typedef struct addr_req {
324 grpc_timer timer;
325 char* addr;
326 grpc_closure* on_done;
327 grpc_resolved_addresses** addrs;
328 grpc_lb_addresses** lb_addrs;
329 } addr_req;
330
finish_resolve(void * arg,grpc_error * error)331 static void finish_resolve(void* arg, grpc_error* error) {
332 addr_req* r = static_cast<addr_req*>(arg);
333
334 if (error == GRPC_ERROR_NONE && 0 == strcmp(r->addr, "server")) {
335 if (r->addrs != nullptr) {
336 grpc_resolved_addresses* addrs =
337 static_cast<grpc_resolved_addresses*>(gpr_malloc(sizeof(*addrs)));
338 addrs->naddrs = 1;
339 addrs->addrs = static_cast<grpc_resolved_address*>(
340 gpr_malloc(sizeof(*addrs->addrs)));
341 addrs->addrs[0].len = 0;
342 *r->addrs = addrs;
343 } else if (r->lb_addrs != nullptr) {
344 grpc_lb_addresses* lb_addrs = grpc_lb_addresses_create(1, nullptr);
345 grpc_lb_addresses_set_address(lb_addrs, 0, nullptr, 0, false, nullptr,
346 nullptr);
347 *r->lb_addrs = lb_addrs;
348 }
349 GRPC_CLOSURE_SCHED(r->on_done, GRPC_ERROR_NONE);
350 } else {
351 GRPC_CLOSURE_SCHED(r->on_done,
352 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
353 "Resolution failed", &error, 1));
354 }
355
356 gpr_free(r->addr);
357 gpr_free(r);
358 }
359
my_resolve_address(const char * addr,const char * default_port,grpc_pollset_set * interested_parties,grpc_closure * on_done,grpc_resolved_addresses ** addresses)360 void my_resolve_address(const char* addr, const char* default_port,
361 grpc_pollset_set* interested_parties,
362 grpc_closure* on_done,
363 grpc_resolved_addresses** addresses) {
364 addr_req* r = static_cast<addr_req*>(gpr_malloc(sizeof(*r)));
365 r->addr = gpr_strdup(addr);
366 r->on_done = on_done;
367 r->addrs = addresses;
368 r->lb_addrs = nullptr;
369 grpc_timer_init(
370 &r->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(),
371 GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx));
372 }
373
374 static grpc_address_resolver_vtable fuzzer_resolver = {my_resolve_address,
375 nullptr};
376
my_dns_lookup_ares_locked(const char * dns_server,const char * addr,const char * default_port,grpc_pollset_set * interested_parties,grpc_closure * on_done,grpc_lb_addresses ** lb_addrs,bool check_grpclb,char ** service_config_json,grpc_combiner * combiner)377 grpc_ares_request* my_dns_lookup_ares_locked(
378 const char* dns_server, const char* addr, const char* default_port,
379 grpc_pollset_set* interested_parties, grpc_closure* on_done,
380 grpc_lb_addresses** lb_addrs, bool check_grpclb, char** service_config_json,
381 grpc_combiner* combiner) {
382 addr_req* r = static_cast<addr_req*>(gpr_malloc(sizeof(*r)));
383 r->addr = gpr_strdup(addr);
384 r->on_done = on_done;
385 r->addrs = nullptr;
386 r->lb_addrs = lb_addrs;
387 grpc_timer_init(
388 &r->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(),
389 GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx));
390 return nullptr;
391 }
392
393 ////////////////////////////////////////////////////////////////////////////////
394 // client connection
395
396 static void sched_connect(grpc_closure* closure, grpc_endpoint** ep,
397 gpr_timespec deadline);
398
399 typedef struct {
400 grpc_timer timer;
401 grpc_closure* closure;
402 grpc_endpoint** ep;
403 gpr_timespec deadline;
404 } future_connect;
405
do_connect(void * arg,grpc_error * error)406 static void do_connect(void* arg, grpc_error* error) {
407 future_connect* fc = static_cast<future_connect*>(arg);
408 if (error != GRPC_ERROR_NONE) {
409 *fc->ep = nullptr;
410 GRPC_CLOSURE_SCHED(fc->closure, GRPC_ERROR_REF(error));
411 } else if (g_server != nullptr) {
412 grpc_endpoint* client;
413 grpc_endpoint* server;
414 grpc_passthru_endpoint_create(&client, &server, g_resource_quota, nullptr);
415 *fc->ep = client;
416
417 grpc_transport* transport =
418 grpc_create_chttp2_transport(nullptr, server, false);
419 grpc_server_setup_transport(g_server, transport, nullptr, nullptr);
420 grpc_chttp2_transport_start_reading(transport, nullptr, nullptr);
421
422 GRPC_CLOSURE_SCHED(fc->closure, GRPC_ERROR_NONE);
423 } else {
424 sched_connect(fc->closure, fc->ep, fc->deadline);
425 }
426 gpr_free(fc);
427 }
428
sched_connect(grpc_closure * closure,grpc_endpoint ** ep,gpr_timespec deadline)429 static void sched_connect(grpc_closure* closure, grpc_endpoint** ep,
430 gpr_timespec deadline) {
431 if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) {
432 *ep = nullptr;
433 GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
434 "Connect deadline exceeded"));
435 return;
436 }
437
438 future_connect* fc = static_cast<future_connect*>(gpr_malloc(sizeof(*fc)));
439 fc->closure = closure;
440 fc->ep = ep;
441 fc->deadline = deadline;
442 grpc_timer_init(
443 &fc->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(),
444 GRPC_CLOSURE_CREATE(do_connect, fc, grpc_schedule_on_exec_ctx));
445 }
446
my_tcp_client_connect(grpc_closure * closure,grpc_endpoint ** ep,grpc_pollset_set * interested_parties,const grpc_channel_args * channel_args,const grpc_resolved_address * addr,grpc_millis deadline)447 static void my_tcp_client_connect(grpc_closure* closure, grpc_endpoint** ep,
448 grpc_pollset_set* interested_parties,
449 const grpc_channel_args* channel_args,
450 const grpc_resolved_address* addr,
451 grpc_millis deadline) {
452 sched_connect(closure, ep,
453 grpc_millis_to_timespec(deadline, GPR_CLOCK_MONOTONIC));
454 }
455
456 grpc_tcp_client_vtable fuzz_tcp_client_vtable = {my_tcp_client_connect};
457
458 ////////////////////////////////////////////////////////////////////////////////
459 // test driver
460
461 typedef struct validator {
462 void (*validate)(void* arg, bool success);
463 void* arg;
464 } validator;
465
create_validator(void (* validate)(void * arg,bool success),void * arg)466 static validator* create_validator(void (*validate)(void* arg, bool success),
467 void* arg) {
468 validator* v = static_cast<validator*>(gpr_malloc(sizeof(*v)));
469 v->validate = validate;
470 v->arg = arg;
471 return v;
472 }
473
assert_success_and_decrement(void * counter,bool success)474 static void assert_success_and_decrement(void* counter, bool success) {
475 GPR_ASSERT(success);
476 --*static_cast<int*>(counter);
477 }
478
decrement(void * counter,bool success)479 static void decrement(void* counter, bool success) {
480 --*static_cast<int*>(counter);
481 }
482
483 typedef struct connectivity_watch {
484 int* counter;
485 gpr_timespec deadline;
486 } connectivity_watch;
487
make_connectivity_watch(gpr_timespec s,int * counter)488 static connectivity_watch* make_connectivity_watch(gpr_timespec s,
489 int* counter) {
490 connectivity_watch* o =
491 static_cast<connectivity_watch*>(gpr_malloc(sizeof(*o)));
492 o->deadline = s;
493 o->counter = counter;
494 return o;
495 }
496
validate_connectivity_watch(void * p,bool success)497 static void validate_connectivity_watch(void* p, bool success) {
498 connectivity_watch* w = static_cast<connectivity_watch*>(p);
499 if (!success) {
500 GPR_ASSERT(gpr_time_cmp(gpr_now(w->deadline.clock_type), w->deadline) >= 0);
501 }
502 --*w->counter;
503 gpr_free(w);
504 }
505
free_non_null(void * p)506 static void free_non_null(void* p) {
507 GPR_ASSERT(p != nullptr);
508 gpr_free(p);
509 }
510
511 typedef enum { ROOT, CLIENT, SERVER, PENDING_SERVER } call_state_type;
512
513 #define DONE_FLAG_CALL_CLOSED ((uint64_t)(1 << 0))
514
515 typedef struct call_state {
516 call_state_type type;
517 grpc_call* call;
518 grpc_byte_buffer* recv_message;
519 grpc_status_code status;
520 grpc_metadata_array recv_initial_metadata;
521 grpc_metadata_array recv_trailing_metadata;
522 grpc_slice recv_status_details;
523 int cancelled;
524 int pending_ops;
525 bool sent_initial_metadata;
526 grpc_call_details call_details;
527 grpc_byte_buffer* send_message;
528 // starts at 0, individual flags from DONE_FLAG_xxx are set
529 // as different operations are completed
530 uint64_t done_flags;
531
532 // array of pointers to free later
533 size_t num_to_free;
534 size_t cap_to_free;
535 void** to_free;
536
537 // array of slices to unref
538 size_t num_slices_to_unref;
539 size_t cap_slices_to_unref;
540 grpc_slice** slices_to_unref;
541
542 struct call_state* next;
543 struct call_state* prev;
544 } call_state;
545
546 static call_state* g_active_call;
547
new_call(call_state * sibling,call_state_type type)548 static call_state* new_call(call_state* sibling, call_state_type type) {
549 call_state* c = static_cast<call_state*>(gpr_malloc(sizeof(*c)));
550 memset(c, 0, sizeof(*c));
551 if (sibling != nullptr) {
552 c->next = sibling;
553 c->prev = sibling->prev;
554 c->next->prev = c->prev->next = c;
555 } else {
556 c->next = c->prev = c;
557 }
558 c->type = type;
559 return c;
560 }
561
maybe_delete_call_state(call_state * call)562 static call_state* maybe_delete_call_state(call_state* call) {
563 call_state* next = call->next;
564
565 if (call->call != nullptr) return next;
566 if (call->pending_ops != 0) return next;
567
568 if (call == g_active_call) {
569 g_active_call = call->next;
570 GPR_ASSERT(call != g_active_call);
571 }
572
573 call->prev->next = call->next;
574 call->next->prev = call->prev;
575 grpc_metadata_array_destroy(&call->recv_initial_metadata);
576 grpc_metadata_array_destroy(&call->recv_trailing_metadata);
577 grpc_slice_unref(call->recv_status_details);
578 grpc_call_details_destroy(&call->call_details);
579
580 for (size_t i = 0; i < call->num_slices_to_unref; i++) {
581 grpc_slice_unref(*call->slices_to_unref[i]);
582 gpr_free(call->slices_to_unref[i]);
583 }
584 for (size_t i = 0; i < call->num_to_free; i++) {
585 gpr_free(call->to_free[i]);
586 }
587 gpr_free(call->to_free);
588 gpr_free(call->slices_to_unref);
589
590 gpr_free(call);
591
592 return next;
593 }
594
add_to_free(call_state * call,void * p)595 static void add_to_free(call_state* call, void* p) {
596 if (call->num_to_free == call->cap_to_free) {
597 call->cap_to_free = GPR_MAX(8, 2 * call->cap_to_free);
598 call->to_free = static_cast<void**>(
599 gpr_realloc(call->to_free, sizeof(*call->to_free) * call->cap_to_free));
600 }
601 call->to_free[call->num_to_free++] = p;
602 }
603
add_slice_to_unref(call_state * call,grpc_slice s)604 static grpc_slice* add_slice_to_unref(call_state* call, grpc_slice s) {
605 if (call->num_slices_to_unref == call->cap_slices_to_unref) {
606 call->cap_slices_to_unref = GPR_MAX(8, 2 * call->cap_slices_to_unref);
607 call->slices_to_unref = static_cast<grpc_slice**>(gpr_realloc(
608 call->slices_to_unref,
609 sizeof(*call->slices_to_unref) * call->cap_slices_to_unref));
610 }
611 call->slices_to_unref[call->num_slices_to_unref] =
612 static_cast<grpc_slice*>(gpr_malloc(sizeof(grpc_slice)));
613 *call->slices_to_unref[call->num_slices_to_unref++] = s;
614 return call->slices_to_unref[call->num_slices_to_unref - 1];
615 }
616
read_metadata(input_stream * inp,size_t * count,grpc_metadata ** metadata,call_state * cs)617 static void read_metadata(input_stream* inp, size_t* count,
618 grpc_metadata** metadata, call_state* cs) {
619 *count = grpc_fuzzer_get_next_byte(inp);
620 if (*count) {
621 *metadata =
622 static_cast<grpc_metadata*>(gpr_malloc(*count * sizeof(**metadata)));
623 memset(*metadata, 0, *count * sizeof(**metadata));
624 for (size_t i = 0; i < *count; i++) {
625 (*metadata)[i].key = read_string_like_slice(inp);
626 (*metadata)[i].value = read_buffer_like_slice(inp);
627 (*metadata)[i].flags = grpc_fuzzer_get_next_uint32(inp);
628 add_slice_to_unref(cs, (*metadata)[i].key);
629 add_slice_to_unref(cs, (*metadata)[i].value);
630 }
631 } else {
632 *metadata = static_cast<grpc_metadata*>(gpr_malloc(1));
633 }
634 add_to_free(cs, *metadata);
635 }
636
destroy_call(call_state * call)637 static call_state* destroy_call(call_state* call) {
638 grpc_call_unref(call->call);
639 call->call = nullptr;
640 return maybe_delete_call_state(call);
641 }
642
finished_request_call(void * csp,bool success)643 static void finished_request_call(void* csp, bool success) {
644 call_state* cs = static_cast<call_state*>(csp);
645 GPR_ASSERT(cs->pending_ops > 0);
646 --cs->pending_ops;
647 if (success) {
648 GPR_ASSERT(cs->call != nullptr);
649 cs->type = SERVER;
650 } else {
651 maybe_delete_call_state(cs);
652 }
653 }
654
655 typedef struct {
656 call_state* cs;
657 uint8_t has_ops;
658 } batch_info;
659
finished_batch(void * p,bool success)660 static void finished_batch(void* p, bool success) {
661 batch_info* bi = static_cast<batch_info*>(p);
662 --bi->cs->pending_ops;
663 if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE)) &&
664 (bi->cs->done_flags & DONE_FLAG_CALL_CLOSED)) {
665 GPR_ASSERT(bi->cs->recv_message == nullptr);
666 }
667 if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE) &&
668 bi->cs->recv_message != nullptr)) {
669 grpc_byte_buffer_destroy(bi->cs->recv_message);
670 bi->cs->recv_message = nullptr;
671 }
672 if ((bi->has_ops & (1u << GRPC_OP_SEND_MESSAGE))) {
673 grpc_byte_buffer_destroy(bi->cs->send_message);
674 bi->cs->send_message = nullptr;
675 }
676 if ((bi->has_ops & (1u << GRPC_OP_RECV_STATUS_ON_CLIENT)) ||
677 (bi->has_ops & (1u << GRPC_OP_RECV_CLOSE_ON_SERVER))) {
678 bi->cs->done_flags |= DONE_FLAG_CALL_CLOSED;
679 }
680 maybe_delete_call_state(bi->cs);
681 gpr_free(bi);
682 }
683
make_finished_batch_validator(call_state * cs,uint8_t has_ops)684 static validator* make_finished_batch_validator(call_state* cs,
685 uint8_t has_ops) {
686 batch_info* bi = static_cast<batch_info*>(gpr_malloc(sizeof(*bi)));
687 bi->cs = cs;
688 bi->has_ops = has_ops;
689 return create_validator(finished_batch, bi);
690 }
691
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)692 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
693 grpc_test_only_set_slice_hash_seed(0);
694 char* grpc_trace_fuzzer = gpr_getenv("GRPC_TRACE_FUZZER");
695 if (squelch && grpc_trace_fuzzer == nullptr) gpr_set_log_function(dont_log);
696 gpr_free(grpc_trace_fuzzer);
697 input_stream inp = {data, data + size};
698 grpc_set_tcp_client_impl(&fuzz_tcp_client_vtable);
699 gpr_now_impl = now_impl;
700 grpc_init();
701 grpc_timer_manager_set_threading(false);
702 {
703 grpc_core::ExecCtx exec_ctx;
704 grpc_executor_set_threading(false);
705 }
706 grpc_set_resolver_impl(&fuzzer_resolver);
707 grpc_dns_lookup_ares_locked = my_dns_lookup_ares_locked;
708
709 GPR_ASSERT(g_channel == nullptr);
710 GPR_ASSERT(g_server == nullptr);
711
712 bool server_shutdown = false;
713 int pending_server_shutdowns = 0;
714 int pending_channel_watches = 0;
715 int pending_pings = 0;
716
717 g_active_call = new_call(nullptr, ROOT);
718 g_resource_quota = grpc_resource_quota_create("api_fuzzer");
719
720 grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
721
722 while (!is_eof(&inp) || g_channel != nullptr || g_server != nullptr ||
723 pending_channel_watches > 0 || pending_pings > 0 ||
724 g_active_call->type != ROOT || g_active_call->next != g_active_call) {
725 if (is_eof(&inp)) {
726 if (g_channel != nullptr) {
727 grpc_channel_destroy(g_channel);
728 g_channel = nullptr;
729 }
730 if (g_server != nullptr) {
731 if (!server_shutdown) {
732 grpc_server_shutdown_and_notify(
733 g_server, cq,
734 create_validator(assert_success_and_decrement,
735 &pending_server_shutdowns));
736 server_shutdown = true;
737 pending_server_shutdowns++;
738 } else if (pending_server_shutdowns == 0) {
739 grpc_server_destroy(g_server);
740 g_server = nullptr;
741 }
742 }
743 call_state* s = g_active_call;
744 do {
745 if (s->type != PENDING_SERVER && s->call != nullptr) {
746 s = destroy_call(s);
747 } else {
748 s = s->next;
749 }
750 } while (s != g_active_call);
751
752 g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN));
753 }
754
755 grpc_timer_manager_tick();
756
757 switch (grpc_fuzzer_get_next_byte(&inp)) {
758 // terminate on bad bytes
759 default:
760 end(&inp);
761 break;
762 // tickle completion queue
763 case 0: {
764 grpc_event ev = grpc_completion_queue_next(
765 cq, gpr_inf_past(GPR_CLOCK_REALTIME), nullptr);
766 switch (ev.type) {
767 case GRPC_OP_COMPLETE: {
768 validator* v = static_cast<validator*>(ev.tag);
769 v->validate(v->arg, ev.success);
770 gpr_free(v);
771 break;
772 }
773 case GRPC_QUEUE_TIMEOUT:
774 break;
775 case GRPC_QUEUE_SHUTDOWN:
776 abort();
777 break;
778 }
779 break;
780 }
781 // increment global time
782 case 1: {
783 g_now = gpr_time_add(
784 g_now, gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp),
785 GPR_TIMESPAN));
786 break;
787 }
788 // create an insecure channel
789 case 2: {
790 if (g_channel == nullptr) {
791 char* target = grpc_fuzzer_get_next_string(&inp, nullptr);
792 char* target_uri;
793 gpr_asprintf(&target_uri, "dns:%s", target);
794 grpc_channel_args* args = read_args(&inp);
795 g_channel = grpc_insecure_channel_create(target_uri, args, nullptr);
796 GPR_ASSERT(g_channel != nullptr);
797 {
798 grpc_core::ExecCtx exec_ctx;
799 grpc_channel_args_destroy(args);
800 }
801 gpr_free(target_uri);
802 gpr_free(target);
803 } else {
804 end(&inp);
805 }
806 break;
807 }
808 // destroy a channel
809 case 3: {
810 if (g_channel != nullptr) {
811 grpc_channel_destroy(g_channel);
812 g_channel = nullptr;
813 } else {
814 end(&inp);
815 }
816 break;
817 }
818 // bring up a server
819 case 4: {
820 if (g_server == nullptr) {
821 grpc_channel_args* args = read_args(&inp);
822 g_server = grpc_server_create(args, nullptr);
823 GPR_ASSERT(g_server != nullptr);
824 {
825 grpc_core::ExecCtx exec_ctx;
826 grpc_channel_args_destroy(args);
827 }
828 grpc_server_register_completion_queue(g_server, cq, nullptr);
829 grpc_server_start(g_server);
830 server_shutdown = false;
831 GPR_ASSERT(pending_server_shutdowns == 0);
832 } else {
833 end(&inp);
834 }
835 break;
836 }
837 // begin server shutdown
838 case 5: {
839 if (g_server != nullptr) {
840 grpc_server_shutdown_and_notify(
841 g_server, cq,
842 create_validator(assert_success_and_decrement,
843 &pending_server_shutdowns));
844 pending_server_shutdowns++;
845 server_shutdown = true;
846 } else {
847 end(&inp);
848 }
849 break;
850 }
851 // cancel all calls if shutdown
852 case 6: {
853 if (g_server != nullptr && server_shutdown) {
854 grpc_server_cancel_all_calls(g_server);
855 } else {
856 end(&inp);
857 }
858 break;
859 }
860 // destroy server
861 case 7: {
862 if (g_server != nullptr && server_shutdown &&
863 pending_server_shutdowns == 0) {
864 grpc_server_destroy(g_server);
865 g_server = nullptr;
866 } else {
867 end(&inp);
868 }
869 break;
870 }
871 // check connectivity
872 case 8: {
873 if (g_channel != nullptr) {
874 uint8_t try_to_connect = grpc_fuzzer_get_next_byte(&inp);
875 if (try_to_connect == 0 || try_to_connect == 1) {
876 grpc_channel_check_connectivity_state(g_channel, try_to_connect);
877 } else {
878 end(&inp);
879 }
880 } else {
881 end(&inp);
882 }
883 break;
884 }
885 // watch connectivity
886 case 9: {
887 if (g_channel != nullptr) {
888 grpc_connectivity_state st =
889 grpc_channel_check_connectivity_state(g_channel, 0);
890 if (st != GRPC_CHANNEL_SHUTDOWN) {
891 gpr_timespec deadline = gpr_time_add(
892 gpr_now(GPR_CLOCK_REALTIME),
893 gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp),
894 GPR_TIMESPAN));
895 grpc_channel_watch_connectivity_state(
896 g_channel, st, deadline, cq,
897 create_validator(validate_connectivity_watch,
898 make_connectivity_watch(
899 deadline, &pending_channel_watches)));
900 pending_channel_watches++;
901 }
902 } else {
903 end(&inp);
904 }
905 break;
906 }
907 // create a call
908 case 10: {
909 bool ok = true;
910 if (g_channel == nullptr) ok = false;
911 grpc_call* parent_call = nullptr;
912 if (g_active_call->type != ROOT) {
913 if (g_active_call->call == nullptr || g_active_call->type == CLIENT) {
914 end(&inp);
915 break;
916 }
917 parent_call = g_active_call->call;
918 }
919 uint32_t propagation_mask = grpc_fuzzer_get_next_uint32(&inp);
920 grpc_slice method = read_string_like_slice(&inp);
921 if (GRPC_SLICE_LENGTH(method) == 0) {
922 ok = false;
923 }
924 grpc_slice host = read_string_like_slice(&inp);
925 gpr_timespec deadline =
926 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
927 gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp),
928 GPR_TIMESPAN));
929
930 if (ok) {
931 call_state* cs = new_call(g_active_call, CLIENT);
932 cs->call =
933 grpc_channel_create_call(g_channel, parent_call, propagation_mask,
934 cq, method, &host, deadline, nullptr);
935 } else {
936 end(&inp);
937 }
938 grpc_slice_unref(method);
939 grpc_slice_unref(host);
940 break;
941 }
942 // switch the 'current' call
943 case 11: {
944 g_active_call = g_active_call->next;
945 break;
946 }
947 // queue some ops on a call
948 case 12: {
949 if (g_active_call->type == PENDING_SERVER ||
950 g_active_call->type == ROOT || g_active_call->call == nullptr) {
951 end(&inp);
952 break;
953 }
954 size_t num_ops = grpc_fuzzer_get_next_byte(&inp);
955 if (num_ops > 6) {
956 end(&inp);
957 break;
958 }
959 grpc_op* ops =
960 static_cast<grpc_op*>(gpr_malloc(sizeof(grpc_op) * num_ops));
961 if (num_ops > 0) memset(ops, 0, sizeof(grpc_op) * num_ops);
962 bool ok = true;
963 size_t i;
964 grpc_op* op;
965 uint8_t has_ops = 0;
966 for (i = 0; i < num_ops; i++) {
967 op = &ops[i];
968 switch (grpc_fuzzer_get_next_byte(&inp)) {
969 default:
970 /* invalid value */
971 op->op = (grpc_op_type)-1;
972 ok = false;
973 break;
974 case GRPC_OP_SEND_INITIAL_METADATA:
975 if (g_active_call->sent_initial_metadata) {
976 ok = false;
977 } else {
978 g_active_call->sent_initial_metadata = true;
979 op->op = GRPC_OP_SEND_INITIAL_METADATA;
980 has_ops |= 1 << GRPC_OP_SEND_INITIAL_METADATA;
981 read_metadata(&inp, &op->data.send_initial_metadata.count,
982 &op->data.send_initial_metadata.metadata,
983 g_active_call);
984 }
985 break;
986 case GRPC_OP_SEND_MESSAGE:
987 op->op = GRPC_OP_SEND_MESSAGE;
988 if (g_active_call->send_message != nullptr) {
989 ok = false;
990 } else {
991 has_ops |= 1 << GRPC_OP_SEND_MESSAGE;
992 g_active_call->send_message =
993 op->data.send_message.send_message = read_message(&inp);
994 }
995 break;
996 case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
997 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
998 has_ops |= 1 << GRPC_OP_SEND_CLOSE_FROM_CLIENT;
999 break;
1000 case GRPC_OP_SEND_STATUS_FROM_SERVER:
1001 op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
1002 has_ops |= 1 << GRPC_OP_SEND_STATUS_FROM_SERVER;
1003 read_metadata(
1004 &inp,
1005 &op->data.send_status_from_server.trailing_metadata_count,
1006 &op->data.send_status_from_server.trailing_metadata,
1007 g_active_call);
1008 op->data.send_status_from_server.status =
1009 static_cast<grpc_status_code>(
1010 grpc_fuzzer_get_next_byte(&inp));
1011 op->data.send_status_from_server.status_details =
1012 add_slice_to_unref(g_active_call,
1013 read_buffer_like_slice(&inp));
1014 break;
1015 case GRPC_OP_RECV_INITIAL_METADATA:
1016 op->op = GRPC_OP_RECV_INITIAL_METADATA;
1017 has_ops |= 1 << GRPC_OP_RECV_INITIAL_METADATA;
1018 op->data.recv_initial_metadata.recv_initial_metadata =
1019 &g_active_call->recv_initial_metadata;
1020 break;
1021 case GRPC_OP_RECV_MESSAGE:
1022 if (g_active_call->done_flags & DONE_FLAG_CALL_CLOSED) {
1023 ok = false;
1024 } else {
1025 op->op = GRPC_OP_RECV_MESSAGE;
1026 has_ops |= 1 << GRPC_OP_RECV_MESSAGE;
1027 op->data.recv_message.recv_message =
1028 &g_active_call->recv_message;
1029 }
1030 break;
1031 case GRPC_OP_RECV_STATUS_ON_CLIENT:
1032 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
1033 op->data.recv_status_on_client.status = &g_active_call->status;
1034 op->data.recv_status_on_client.trailing_metadata =
1035 &g_active_call->recv_trailing_metadata;
1036 op->data.recv_status_on_client.status_details =
1037 &g_active_call->recv_status_details;
1038 break;
1039 case GRPC_OP_RECV_CLOSE_ON_SERVER:
1040 op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
1041 has_ops |= 1 << GRPC_OP_RECV_CLOSE_ON_SERVER;
1042 op->data.recv_close_on_server.cancelled =
1043 &g_active_call->cancelled;
1044 break;
1045 }
1046 op->reserved = nullptr;
1047 op->flags = grpc_fuzzer_get_next_uint32(&inp);
1048 }
1049 if (g_channel == nullptr) ok = false;
1050 if (ok) {
1051 validator* v = make_finished_batch_validator(g_active_call, has_ops);
1052 g_active_call->pending_ops++;
1053 grpc_call_error error = grpc_call_start_batch(
1054 g_active_call->call, ops, num_ops, v, nullptr);
1055 if (error != GRPC_CALL_OK) {
1056 v->validate(v->arg, false);
1057 gpr_free(v);
1058 }
1059 } else {
1060 end(&inp);
1061 }
1062 if (!ok && (has_ops & (1 << GRPC_OP_SEND_MESSAGE))) {
1063 grpc_byte_buffer_destroy(g_active_call->send_message);
1064 g_active_call->send_message = nullptr;
1065 }
1066 gpr_free(ops);
1067
1068 break;
1069 }
1070 // cancel current call
1071 case 13: {
1072 if (g_active_call->type != ROOT && g_active_call->call != nullptr) {
1073 grpc_call_cancel(g_active_call->call, nullptr);
1074 } else {
1075 end(&inp);
1076 }
1077 break;
1078 }
1079 // get a calls peer
1080 case 14: {
1081 if (g_active_call->type != ROOT && g_active_call->call != nullptr) {
1082 free_non_null(grpc_call_get_peer(g_active_call->call));
1083 } else {
1084 end(&inp);
1085 }
1086 break;
1087 }
1088 // get a channels target
1089 case 15: {
1090 if (g_channel != nullptr) {
1091 free_non_null(grpc_channel_get_target(g_channel));
1092 } else {
1093 end(&inp);
1094 }
1095 break;
1096 }
1097 // send a ping on a channel
1098 case 16: {
1099 if (g_channel != nullptr) {
1100 pending_pings++;
1101 grpc_channel_ping(g_channel, cq,
1102 create_validator(decrement, &pending_pings),
1103 nullptr);
1104 } else {
1105 end(&inp);
1106 }
1107 break;
1108 }
1109 // enable a tracer
1110 case 17: {
1111 char* tracer = grpc_fuzzer_get_next_string(&inp, nullptr);
1112 grpc_tracer_set_enabled(tracer, 1);
1113 gpr_free(tracer);
1114 break;
1115 }
1116 // disable a tracer
1117 case 18: {
1118 char* tracer = grpc_fuzzer_get_next_string(&inp, nullptr);
1119 grpc_tracer_set_enabled(tracer, 0);
1120 gpr_free(tracer);
1121 break;
1122 }
1123 // request a server call
1124 case 19: {
1125 if (g_server == nullptr) {
1126 end(&inp);
1127 break;
1128 }
1129 call_state* cs = new_call(g_active_call, PENDING_SERVER);
1130 cs->pending_ops++;
1131 validator* v = create_validator(finished_request_call, cs);
1132 grpc_call_error error =
1133 grpc_server_request_call(g_server, &cs->call, &cs->call_details,
1134 &cs->recv_initial_metadata, cq, cq, v);
1135 if (error != GRPC_CALL_OK) {
1136 v->validate(v->arg, false);
1137 gpr_free(v);
1138 }
1139 break;
1140 }
1141 // destroy a call
1142 case 20: {
1143 if (g_active_call->type != ROOT &&
1144 g_active_call->type != PENDING_SERVER &&
1145 g_active_call->call != nullptr) {
1146 destroy_call(g_active_call);
1147 } else {
1148 end(&inp);
1149 }
1150 break;
1151 }
1152 // resize the buffer pool
1153 case 21: {
1154 grpc_resource_quota_resize(g_resource_quota, read_uint22(&inp));
1155 break;
1156 }
1157 // create a secure channel
1158 case 22: {
1159 if (g_channel == nullptr) {
1160 char* target = grpc_fuzzer_get_next_string(&inp, nullptr);
1161 char* target_uri;
1162 gpr_asprintf(&target_uri, "dns:%s", target);
1163 grpc_channel_args* args = read_args(&inp);
1164 grpc_channel_credentials* creds = read_channel_creds(&inp);
1165 g_channel =
1166 grpc_secure_channel_create(creds, target_uri, args, nullptr);
1167 GPR_ASSERT(g_channel != nullptr);
1168 {
1169 grpc_core::ExecCtx exec_ctx;
1170 grpc_channel_args_destroy(args);
1171 }
1172 gpr_free(target_uri);
1173 gpr_free(target);
1174 grpc_channel_credentials_release(creds);
1175 } else {
1176 end(&inp);
1177 }
1178 break;
1179 }
1180 }
1181 }
1182
1183 GPR_ASSERT(g_channel == nullptr);
1184 GPR_ASSERT(g_server == nullptr);
1185 GPR_ASSERT(g_active_call->type == ROOT);
1186 GPR_ASSERT(g_active_call->next == g_active_call);
1187 gpr_free(g_active_call);
1188
1189 grpc_completion_queue_shutdown(cq);
1190 GPR_ASSERT(
1191 grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), nullptr)
1192 .type == GRPC_QUEUE_SHUTDOWN);
1193 grpc_completion_queue_destroy(cq);
1194
1195 grpc_resource_quota_unref(g_resource_quota);
1196
1197 grpc_shutdown();
1198 return 0;
1199 }
1200