From ff8fecb7f2be482ddd7c84cf5c16ed85ac56705a Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 27 Feb 2020 16:10:31 -0800 Subject: [PATCH] Delete api_fuzzer.cc --- test/core/end2end/fuzzers/api_fuzzer.cc | 1206 ----------------------- 1 file changed, 1206 deletions(-) delete mode 100644 test/core/end2end/fuzzers/api_fuzzer.cc diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc deleted file mode 100644 index 7b9883f29f8..00000000000 --- a/test/core/end2end/fuzzers/api_fuzzer.cc +++ /dev/null @@ -1,1206 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include -#include -#include - -#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" -#include "src/core/ext/filters/client_channel/server_address.h" -#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/env.h" -#include "src/core/lib/iomgr/executor.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/tcp_client.h" -#include "src/core/lib/iomgr/timer.h" -#include "src/core/lib/iomgr/timer_manager.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/surface/server.h" -#include "src/core/lib/transport/metadata.h" -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/util/fuzzer_util.h" -#include "test/core/util/passthru_endpoint.h" - -using grpc_core::testing::grpc_fuzzer_get_next_byte; -using grpc_core::testing::grpc_fuzzer_get_next_string; -using grpc_core::testing::grpc_fuzzer_get_next_uint32; -using grpc_core::testing::input_stream; - -//////////////////////////////////////////////////////////////////////////////// -// logging - -bool squelch = true; -bool leak_check = true; - -static void dont_log(gpr_log_func_args* /*args*/) {} - -//////////////////////////////////////////////////////////////////////////////// -// global state - -static gpr_timespec g_now; -static grpc_server* g_server; -static grpc_channel* g_channel; -static grpc_resource_quota* g_resource_quota; - -extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); - -static gpr_timespec now_impl(gpr_clock_type clock_type) { - GPR_ASSERT(clock_type != GPR_TIMESPAN); - gpr_timespec ts = g_now; - ts.clock_type = clock_type; - return ts; -} - -static void end(input_stream* inp) { inp->cur = inp->end; } - -static void read_buffer(input_stream* inp, char** buffer, size_t* length, - bool* special) { - *length = grpc_fuzzer_get_next_byte(inp); - if (*length == 255) { - if (special != nullptr) *special = true; - *length = grpc_fuzzer_get_next_byte(inp); - } else { - if (special != nullptr) *special = false; - } - *buffer = static_cast(gpr_malloc(*length)); - for (size_t i = 0; i < *length; i++) { - (*buffer)[i] = static_cast(grpc_fuzzer_get_next_byte(inp)); - } -} - -static grpc_slice maybe_intern(grpc_slice s, bool intern) { - grpc_slice r = intern ? grpc_slice_intern(s) : grpc_slice_ref(s); - grpc_slice_unref(s); - return r; -} - -static grpc_slice read_string_like_slice(input_stream* inp) { - bool special; - char* s = grpc_fuzzer_get_next_string(inp, &special); - grpc_slice r = maybe_intern(grpc_slice_from_copied_string(s), special); - gpr_free(s); - return r; -} - -static grpc_slice read_buffer_like_slice(input_stream* inp) { - char* buffer; - size_t length; - bool special; - read_buffer(inp, &buffer, &length, &special); - grpc_slice r = - maybe_intern(grpc_slice_from_copied_buffer(buffer, length), special); - gpr_free(buffer); - return r; -} - -static uint32_t read_uint22(input_stream* inp) { - uint8_t b = grpc_fuzzer_get_next_byte(inp); - uint32_t x = b & 0x7f; - if (b & 0x80) { - x <<= 7; - b = grpc_fuzzer_get_next_byte(inp); - x |= b & 0x7f; - if (b & 0x80) { - x <<= 8; - x |= grpc_fuzzer_get_next_byte(inp); - } - } - return x; -} - -static grpc_byte_buffer* read_message(input_stream* inp) { - grpc_slice slice = grpc_slice_malloc(read_uint22(inp)); - memset(GRPC_SLICE_START_PTR(slice), 0, GRPC_SLICE_LENGTH(slice)); - grpc_byte_buffer* out = grpc_raw_byte_buffer_create(&slice, 1); - grpc_slice_unref(slice); - return out; -} - -static int read_int(input_stream* inp) { - return static_cast(grpc_fuzzer_get_next_uint32(inp)); -} - -static grpc_channel_args* read_args(input_stream* inp) { - size_t n = grpc_fuzzer_get_next_byte(inp); - grpc_arg* args = static_cast(gpr_malloc(sizeof(*args) * n)); - for (size_t i = 0; i < n; i++) { - switch (grpc_fuzzer_get_next_byte(inp)) { - case 1: - args[i].type = GRPC_ARG_STRING; - args[i].key = grpc_fuzzer_get_next_string(inp, nullptr); - args[i].value.string = grpc_fuzzer_get_next_string(inp, nullptr); - break; - case 2: - args[i].type = GRPC_ARG_INTEGER; - args[i].key = grpc_fuzzer_get_next_string(inp, nullptr); - args[i].value.integer = read_int(inp); - break; - case 3: - args[i].type = GRPC_ARG_POINTER; - args[i].key = gpr_strdup(GRPC_ARG_RESOURCE_QUOTA); - args[i].value.pointer.vtable = grpc_resource_quota_arg_vtable(); - args[i].value.pointer.p = g_resource_quota; - grpc_resource_quota_ref(g_resource_quota); - break; - default: - end(inp); - n = i; - break; - } - } - grpc_channel_args* a = - static_cast(gpr_malloc(sizeof(*a))); - a->args = args; - a->num_args = n; - return a; -} - -typedef struct cred_artifact_ctx { - int num_release; - char* release[3]; -} cred_artifact_ctx; -#define CRED_ARTIFACT_CTX_INIT \ - { \ - 0, { 0 } \ - } - -static void cred_artifact_ctx_finish(cred_artifact_ctx* ctx) { - for (int i = 0; i < ctx->num_release; i++) { - gpr_free(ctx->release[i]); - } -} - -static const char* read_cred_artifact(cred_artifact_ctx* ctx, input_stream* inp, - const char** builtins, - size_t num_builtins) { - uint8_t b = grpc_fuzzer_get_next_byte(inp); - if (b == 0) return nullptr; - if (b == 1) - return ctx->release[ctx->num_release++] = - grpc_fuzzer_get_next_string(inp, nullptr); - if (b >= num_builtins + 1) { - end(inp); - return nullptr; - } - return builtins[b - 1]; -} - -static grpc_channel_credentials* read_ssl_channel_creds(input_stream* inp) { - cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; - static const char* builtin_root_certs[] = {test_root_cert}; - static const char* builtin_private_keys[] = { - test_server1_key, test_self_signed_client_key, test_signed_client_key}; - static const char* builtin_cert_chains[] = { - test_server1_cert, test_self_signed_client_cert, test_signed_client_cert}; - const char* root_certs = read_cred_artifact( - &ctx, inp, builtin_root_certs, GPR_ARRAY_SIZE(builtin_root_certs)); - const char* private_key = read_cred_artifact( - &ctx, inp, builtin_private_keys, GPR_ARRAY_SIZE(builtin_private_keys)); - const char* certs = read_cred_artifact(&ctx, inp, builtin_cert_chains, - GPR_ARRAY_SIZE(builtin_cert_chains)); - grpc_ssl_pem_key_cert_pair key_cert_pair = {private_key, certs}; - grpc_channel_credentials* creds = grpc_ssl_credentials_create( - root_certs, - private_key != nullptr && certs != nullptr ? &key_cert_pair : nullptr, - nullptr, nullptr); - cred_artifact_ctx_finish(&ctx); - return creds; -} - -static grpc_call_credentials* read_call_creds(input_stream* inp, int depth) { - if (depth > 64) { - // prevent creating infinitely deep call creds - end(inp); - return nullptr; - } - switch (grpc_fuzzer_get_next_byte(inp)) { - default: - end(inp); - return nullptr; - case 0: - return nullptr; - case 1: { - grpc_call_credentials* c1 = read_call_creds(inp, depth + 1); - grpc_call_credentials* c2 = read_call_creds(inp, depth + 1); - if (c1 != nullptr && c2 != nullptr) { - grpc_call_credentials* out = - grpc_composite_call_credentials_create(c1, c2, nullptr); - grpc_call_credentials_release(c1); - grpc_call_credentials_release(c2); - return out; - } else if (c1 != nullptr) { - return c1; - } else if (c2 != nullptr) { - return c2; - } else { - return nullptr; - } - GPR_UNREACHABLE_CODE(return nullptr); - } - case 2: { - cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; - const char* access_token = read_cred_artifact(&ctx, inp, nullptr, 0); - grpc_call_credentials* out = - access_token == nullptr - ? nullptr - : grpc_access_token_credentials_create(access_token, nullptr); - cred_artifact_ctx_finish(&ctx); - return out; - } - case 3: { - cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT; - const char* auth_token = read_cred_artifact(&ctx, inp, nullptr, 0); - const char* auth_selector = read_cred_artifact(&ctx, inp, nullptr, 0); - grpc_call_credentials* out = - auth_token == nullptr || auth_selector == nullptr - ? nullptr - : grpc_google_iam_credentials_create(auth_token, auth_selector, - nullptr); - cred_artifact_ctx_finish(&ctx); - return out; - } - /* TODO(ctiller): more cred types here */ - } -} - -static grpc_channel_credentials* read_channel_creds(input_stream* inp) { - switch (grpc_fuzzer_get_next_byte(inp)) { - case 0: - return read_ssl_channel_creds(inp); - break; - case 1: { - grpc_channel_credentials* c1 = read_channel_creds(inp); - grpc_call_credentials* c2 = read_call_creds(inp, 0); - if (c1 != nullptr && c2 != nullptr) { - grpc_channel_credentials* out = - grpc_composite_channel_credentials_create(c1, c2, nullptr); - grpc_channel_credentials_release(c1); - grpc_call_credentials_release(c2); - return out; - } else if (c1) { - return c1; - } else if (c2) { - grpc_call_credentials_release(c2); - return nullptr; - } else { - return nullptr; - } - GPR_UNREACHABLE_CODE(return nullptr); - } - case 2: - return nullptr; - default: - end(inp); - return nullptr; - } -} - -static bool is_eof(input_stream* inp) { return inp->cur == inp->end; } - -//////////////////////////////////////////////////////////////////////////////// -// dns resolution - -typedef struct addr_req { - grpc_timer timer; - char* addr; - grpc_closure* on_done; - grpc_resolved_addresses** addrs; - std::unique_ptr* addresses; -} addr_req; - -static void finish_resolve(void* arg, grpc_error* error) { - addr_req* r = static_cast(arg); - - if (error == GRPC_ERROR_NONE && 0 == strcmp(r->addr, "server")) { - if (r->addrs != nullptr) { - grpc_resolved_addresses* addrs = - static_cast(gpr_malloc(sizeof(*addrs))); - addrs->naddrs = 1; - addrs->addrs = static_cast( - gpr_malloc(sizeof(*addrs->addrs))); - addrs->addrs[0].len = 0; - *r->addrs = addrs; - } else if (r->addresses != nullptr) { - *r->addresses = absl::make_unique(); - grpc_resolved_address dummy_resolved_address; - memset(&dummy_resolved_address, 0, sizeof(dummy_resolved_address)); - dummy_resolved_address.len = 0; - (*r->addresses)->emplace_back(dummy_resolved_address, nullptr); - } - grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, GRPC_ERROR_NONE); - } else { - grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Resolution failed", &error, 1)); - } - - gpr_free(r->addr); - delete r; -} - -void my_resolve_address(const char* addr, const char* /*default_port*/, - grpc_pollset_set* /*interested_parties*/, - grpc_closure* on_done, - grpc_resolved_addresses** addrs) { - addr_req* r = new addr_req(); - r->addr = gpr_strdup(addr); - r->on_done = on_done; - r->addrs = addrs; - grpc_timer_init( - &r->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(), - GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx)); -} - -static grpc_address_resolver_vtable fuzzer_resolver = {my_resolve_address, - nullptr}; - -grpc_ares_request* 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, - std::unique_ptr* addresses, - bool /*check_grpclb*/, char** /*service_config_json*/, - int /*query_timeout*/, grpc_core::Combiner* /*combiner*/) { - addr_req* r = static_cast(gpr_malloc(sizeof(*r))); - r->addr = gpr_strdup(addr); - r->on_done = on_done; - r->addrs = nullptr; - r->addresses = addresses; - grpc_timer_init( - &r->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(), - GRPC_CLOSURE_CREATE(finish_resolve, r, grpc_schedule_on_exec_ctx)); - return nullptr; -} - -static void my_cancel_ares_request_locked(grpc_ares_request* request) { - GPR_ASSERT(request == nullptr); -} - -//////////////////////////////////////////////////////////////////////////////// -// client connection - -static void sched_connect(grpc_closure* closure, grpc_endpoint** ep, - gpr_timespec deadline); - -typedef struct { - grpc_timer timer; - grpc_closure* closure; - grpc_endpoint** ep; - gpr_timespec deadline; -} future_connect; - -static void do_connect(void* arg, grpc_error* error) { - future_connect* fc = static_cast(arg); - if (error != GRPC_ERROR_NONE) { - *fc->ep = nullptr; - grpc_core::ExecCtx::Run(DEBUG_LOCATION, fc->closure, GRPC_ERROR_REF(error)); - } else if (g_server != nullptr) { - grpc_endpoint* client; - grpc_endpoint* server; - grpc_passthru_endpoint_create(&client, &server, g_resource_quota, nullptr); - *fc->ep = client; - - grpc_transport* transport = - grpc_create_chttp2_transport(nullptr, server, false); - grpc_server_setup_transport(g_server, transport, nullptr, nullptr, nullptr); - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); - - grpc_core::ExecCtx::Run(DEBUG_LOCATION, fc->closure, GRPC_ERROR_NONE); - } else { - sched_connect(fc->closure, fc->ep, fc->deadline); - } - gpr_free(fc); -} - -static void sched_connect(grpc_closure* closure, grpc_endpoint** ep, - gpr_timespec deadline) { - if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) { - *ep = nullptr; - grpc_core::ExecCtx::Run( - DEBUG_LOCATION, closure, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connect deadline exceeded")); - return; - } - - future_connect* fc = static_cast(gpr_malloc(sizeof(*fc))); - fc->closure = closure; - fc->ep = ep; - fc->deadline = deadline; - grpc_timer_init( - &fc->timer, GPR_MS_PER_SEC + grpc_core::ExecCtx::Get()->Now(), - GRPC_CLOSURE_CREATE(do_connect, fc, grpc_schedule_on_exec_ctx)); -} - -static void 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) { - sched_connect(closure, ep, - grpc_millis_to_timespec(deadline, GPR_CLOCK_MONOTONIC)); -} - -grpc_tcp_client_vtable fuzz_tcp_client_vtable = {my_tcp_client_connect}; - -//////////////////////////////////////////////////////////////////////////////// -// test driver - -typedef struct validator { - void (*validate)(void* arg, bool success); - void* arg; -} validator; - -static validator* create_validator(void (*validate)(void* arg, bool success), - void* arg) { - validator* v = static_cast(gpr_malloc(sizeof(*v))); - v->validate = validate; - v->arg = arg; - return v; -} - -static void assert_success_and_decrement(void* counter, bool success) { - GPR_ASSERT(success); - --*static_cast(counter); -} - -static void decrement(void* counter, bool /*success*/) { - --*static_cast(counter); -} - -typedef struct connectivity_watch { - int* counter; - gpr_timespec deadline; -} connectivity_watch; - -static connectivity_watch* make_connectivity_watch(gpr_timespec s, - int* counter) { - connectivity_watch* o = - static_cast(gpr_malloc(sizeof(*o))); - o->deadline = s; - o->counter = counter; - return o; -} - -static void validate_connectivity_watch(void* p, bool success) { - connectivity_watch* w = static_cast(p); - if (!success) { - GPR_ASSERT(gpr_time_cmp(gpr_now(w->deadline.clock_type), w->deadline) >= 0); - } - --*w->counter; - gpr_free(w); -} - -static void free_non_null(void* p) { - GPR_ASSERT(p != nullptr); - gpr_free(p); -} - -typedef enum { ROOT, CLIENT, SERVER, PENDING_SERVER } call_state_type; - -#define DONE_FLAG_CALL_CLOSED ((uint64_t)(1 << 0)) - -typedef struct call_state { - call_state_type type; - grpc_call* call; - grpc_byte_buffer* recv_message; - grpc_status_code status; - grpc_metadata_array recv_initial_metadata; - grpc_metadata_array recv_trailing_metadata; - grpc_slice recv_status_details; - int cancelled; - int pending_ops; - bool sent_initial_metadata; - grpc_call_details call_details; - grpc_byte_buffer* send_message; - // starts at 0, individual flags from DONE_FLAG_xxx are set - // as different operations are completed - uint64_t done_flags; - - // array of pointers to free later - size_t num_to_free; - size_t cap_to_free; - void** to_free; - - // array of slices to unref - size_t num_slices_to_unref; - size_t cap_slices_to_unref; - grpc_slice** slices_to_unref; - - 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 = static_cast(gpr_malloc(sizeof(*c))); - memset(c, 0, sizeof(*c)); - if (sibling != nullptr) { - c->next = sibling; - c->prev = sibling->prev; - c->next->prev = c->prev->next = c; - } else { - c->next = c->prev = c; - } - c->type = type; - return c; -} - -static call_state* maybe_delete_call_state(call_state* call) { - call_state* next = call->next; - - if (call->call != nullptr) return next; - if (call->pending_ops != 0) return next; - - if (call == g_active_call) { - g_active_call = call->next; - GPR_ASSERT(call != g_active_call); - } - - call->prev->next = call->next; - call->next->prev = call->prev; - grpc_metadata_array_destroy(&call->recv_initial_metadata); - grpc_metadata_array_destroy(&call->recv_trailing_metadata); - grpc_slice_unref(call->recv_status_details); - grpc_call_details_destroy(&call->call_details); - - for (size_t i = 0; i < call->num_slices_to_unref; i++) { - grpc_slice_unref(*call->slices_to_unref[i]); - gpr_free(call->slices_to_unref[i]); - } - for (size_t i = 0; i < call->num_to_free; i++) { - gpr_free(call->to_free[i]); - } - gpr_free(call->to_free); - gpr_free(call->slices_to_unref); - - gpr_free(call); - - return next; -} - -static void add_to_free(call_state* call, void* p) { - if (call->num_to_free == call->cap_to_free) { - call->cap_to_free = GPR_MAX(8, 2 * call->cap_to_free); - call->to_free = static_cast( - gpr_realloc(call->to_free, sizeof(*call->to_free) * call->cap_to_free)); - } - call->to_free[call->num_to_free++] = p; -} - -static grpc_slice* add_slice_to_unref(call_state* call, grpc_slice s) { - if (call->num_slices_to_unref == call->cap_slices_to_unref) { - call->cap_slices_to_unref = GPR_MAX(8, 2 * call->cap_slices_to_unref); - call->slices_to_unref = static_cast(gpr_realloc( - call->slices_to_unref, - sizeof(*call->slices_to_unref) * call->cap_slices_to_unref)); - } - call->slices_to_unref[call->num_slices_to_unref] = - static_cast(gpr_malloc(sizeof(grpc_slice))); - *call->slices_to_unref[call->num_slices_to_unref++] = s; - return call->slices_to_unref[call->num_slices_to_unref - 1]; -} - -static void read_metadata(input_stream* inp, size_t* count, - grpc_metadata** metadata, call_state* cs) { - *count = grpc_fuzzer_get_next_byte(inp); - if (*count) { - *metadata = - static_cast(gpr_malloc(*count * sizeof(**metadata))); - memset(*metadata, 0, *count * sizeof(**metadata)); - for (size_t i = 0; i < *count; i++) { - (*metadata)[i].key = read_string_like_slice(inp); - (*metadata)[i].value = read_buffer_like_slice(inp); - (*metadata)[i].flags = grpc_fuzzer_get_next_uint32(inp); - add_slice_to_unref(cs, (*metadata)[i].key); - add_slice_to_unref(cs, (*metadata)[i].value); - } - } else { - *metadata = static_cast(gpr_malloc(1)); - } - add_to_free(cs, *metadata); -} - -static call_state* destroy_call(call_state* call) { - grpc_call_unref(call->call); - call->call = nullptr; - return maybe_delete_call_state(call); -} - -static void finished_request_call(void* csp, bool success) { - call_state* cs = static_cast(csp); - GPR_ASSERT(cs->pending_ops > 0); - --cs->pending_ops; - if (success) { - GPR_ASSERT(cs->call != nullptr); - cs->type = SERVER; - } else { - maybe_delete_call_state(cs); - } -} - -typedef struct { - call_state* cs; - uint8_t has_ops; -} batch_info; - -static void finished_batch(void* p, bool /*success*/) { - batch_info* bi = static_cast(p); - --bi->cs->pending_ops; - if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE)) && - (bi->cs->done_flags & DONE_FLAG_CALL_CLOSED)) { - GPR_ASSERT(bi->cs->recv_message == nullptr); - } - if ((bi->has_ops & (1u << GRPC_OP_RECV_MESSAGE) && - bi->cs->recv_message != nullptr)) { - grpc_byte_buffer_destroy(bi->cs->recv_message); - bi->cs->recv_message = nullptr; - } - if ((bi->has_ops & (1u << GRPC_OP_SEND_MESSAGE))) { - grpc_byte_buffer_destroy(bi->cs->send_message); - bi->cs->send_message = nullptr; - } - if ((bi->has_ops & (1u << GRPC_OP_RECV_STATUS_ON_CLIENT)) || - (bi->has_ops & (1u << GRPC_OP_RECV_CLOSE_ON_SERVER))) { - bi->cs->done_flags |= DONE_FLAG_CALL_CLOSED; - } - maybe_delete_call_state(bi->cs); - gpr_free(bi); -} - -static validator* make_finished_batch_validator(call_state* cs, - uint8_t has_ops) { - batch_info* bi = static_cast(gpr_malloc(sizeof(*bi))); - bi->cs = cs; - bi->has_ops = has_ops; - return create_validator(finished_batch, bi); -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - grpc_test_only_set_slice_hash_seed(0); - char* grpc_trace_fuzzer = gpr_getenv("GRPC_TRACE_FUZZER"); - if (squelch && grpc_trace_fuzzer == nullptr) gpr_set_log_function(dont_log); - gpr_free(grpc_trace_fuzzer); - input_stream inp = {data, data + size}; - grpc_set_tcp_client_impl(&fuzz_tcp_client_vtable); - gpr_now_impl = now_impl; - grpc_init(); - grpc_timer_manager_set_threading(false); - { - grpc_core::ExecCtx exec_ctx; - grpc_core::Executor::SetThreadingAll(false); - } - grpc_set_resolver_impl(&fuzzer_resolver); - grpc_dns_lookup_ares_locked = my_dns_lookup_ares_locked; - grpc_cancel_ares_request_locked = my_cancel_ares_request_locked; - - GPR_ASSERT(g_channel == nullptr); - GPR_ASSERT(g_server == nullptr); - - bool server_shutdown = false; - int pending_server_shutdowns = 0; - int pending_channel_watches = 0; - int pending_pings = 0; - - g_active_call = new_call(nullptr, ROOT); - g_resource_quota = grpc_resource_quota_create("api_fuzzer"); - - grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); - - while (!is_eof(&inp) || g_channel != nullptr || g_server != nullptr || - 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 != nullptr) { - grpc_channel_destroy(g_channel); - g_channel = nullptr; - } - if (g_server != nullptr) { - if (!server_shutdown) { - grpc_server_shutdown_and_notify( - g_server, cq, - create_validator(assert_success_and_decrement, - &pending_server_shutdowns)); - server_shutdown = true; - pending_server_shutdowns++; - } else if (pending_server_shutdowns == 0) { - grpc_server_destroy(g_server); - g_server = nullptr; - } - } - call_state* s = g_active_call; - do { - if (s->type != PENDING_SERVER && s->call != nullptr) { - s = destroy_call(s); - } else { - s = s->next; - } - } while (s != g_active_call); - - g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN)); - } - - grpc_timer_manager_tick(); - - switch (grpc_fuzzer_get_next_byte(&inp)) { - // terminate on bad bytes - default: - end(&inp); - break; - // tickle completion queue - case 0: { - grpc_event ev = grpc_completion_queue_next( - cq, gpr_inf_past(GPR_CLOCK_REALTIME), nullptr); - switch (ev.type) { - case GRPC_OP_COMPLETE: { - validator* v = static_cast(ev.tag); - v->validate(v->arg, ev.success); - gpr_free(v); - break; - } - case GRPC_QUEUE_TIMEOUT: - break; - case GRPC_QUEUE_SHUTDOWN: - abort(); - break; - } - break; - } - // increment global time - case 1: { - g_now = gpr_time_add( - g_now, gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp), - GPR_TIMESPAN)); - break; - } - // create an insecure channel - case 2: { - if (g_channel == nullptr) { - char* target = grpc_fuzzer_get_next_string(&inp, nullptr); - char* target_uri; - gpr_asprintf(&target_uri, "dns:%s", target); - grpc_channel_args* args = read_args(&inp); - g_channel = grpc_insecure_channel_create(target_uri, args, nullptr); - GPR_ASSERT(g_channel != nullptr); - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(args); - } - gpr_free(target_uri); - gpr_free(target); - } else { - end(&inp); - } - break; - } - // destroy a channel - case 3: { - if (g_channel != nullptr) { - grpc_channel_destroy(g_channel); - g_channel = nullptr; - } else { - end(&inp); - } - break; - } - // bring up a server - case 4: { - if (g_server == nullptr) { - grpc_channel_args* args = read_args(&inp); - g_server = grpc_server_create(args, nullptr); - GPR_ASSERT(g_server != nullptr); - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(args); - } - grpc_server_register_completion_queue(g_server, cq, nullptr); - grpc_server_start(g_server); - server_shutdown = false; - GPR_ASSERT(pending_server_shutdowns == 0); - } else { - end(&inp); - } - break; - } - // begin server shutdown - case 5: { - if (g_server != nullptr) { - grpc_server_shutdown_and_notify( - g_server, cq, - create_validator(assert_success_and_decrement, - &pending_server_shutdowns)); - pending_server_shutdowns++; - server_shutdown = true; - } else { - end(&inp); - } - break; - } - // cancel all calls if shutdown - case 6: { - if (g_server != nullptr && server_shutdown) { - grpc_server_cancel_all_calls(g_server); - } else { - end(&inp); - } - break; - } - // destroy server - case 7: { - if (g_server != nullptr && server_shutdown && - pending_server_shutdowns == 0) { - grpc_server_destroy(g_server); - g_server = nullptr; - } else { - end(&inp); - } - break; - } - // check connectivity - case 8: { - if (g_channel != nullptr) { - uint8_t try_to_connect = grpc_fuzzer_get_next_byte(&inp); - if (try_to_connect == 0 || try_to_connect == 1) { - grpc_channel_check_connectivity_state(g_channel, try_to_connect); - } else { - end(&inp); - } - } else { - end(&inp); - } - break; - } - // watch connectivity - case 9: { - if (g_channel != nullptr) { - grpc_connectivity_state st = - grpc_channel_check_connectivity_state(g_channel, 0); - if (st != GRPC_CHANNEL_SHUTDOWN) { - gpr_timespec deadline = gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp), - GPR_TIMESPAN)); - grpc_channel_watch_connectivity_state( - g_channel, st, deadline, cq, - create_validator(validate_connectivity_watch, - make_connectivity_watch( - deadline, &pending_channel_watches))); - pending_channel_watches++; - } - } else { - end(&inp); - } - break; - } - // create a call - case 10: { - bool ok = true; - if (g_channel == nullptr) ok = false; - grpc_call* parent_call = nullptr; - if (g_active_call->type != ROOT) { - if (g_active_call->call == nullptr || g_active_call->type == CLIENT) { - end(&inp); - break; - } - parent_call = g_active_call->call; - } - uint32_t propagation_mask = grpc_fuzzer_get_next_uint32(&inp); - grpc_slice method = read_string_like_slice(&inp); - if (GRPC_SLICE_LENGTH(method) == 0) { - ok = false; - } - grpc_slice host = read_string_like_slice(&inp); - gpr_timespec deadline = - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp), - GPR_TIMESPAN)); - - if (ok) { - 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, nullptr); - } else { - end(&inp); - } - grpc_slice_unref(method); - grpc_slice_unref(host); - break; - } - // switch the 'current' call - case 11: { - g_active_call = g_active_call->next; - break; - } - // queue some ops on a call - case 12: { - if (g_active_call->type == PENDING_SERVER || - g_active_call->type == ROOT || g_active_call->call == nullptr) { - end(&inp); - break; - } - size_t num_ops = grpc_fuzzer_get_next_byte(&inp); - if (num_ops > 6) { - end(&inp); - break; - } - grpc_op* ops = - static_cast(gpr_malloc(sizeof(grpc_op) * num_ops)); - if (num_ops > 0) memset(ops, 0, sizeof(grpc_op) * num_ops); - bool ok = true; - size_t i; - grpc_op* op; - uint8_t has_ops = 0; - for (i = 0; i < num_ops; i++) { - op = &ops[i]; - switch (grpc_fuzzer_get_next_byte(&inp)) { - default: - /* invalid value */ - op->op = (grpc_op_type)-1; - ok = false; - break; - case GRPC_OP_SEND_INITIAL_METADATA: - if (g_active_call->sent_initial_metadata) { - ok = false; - } else { - g_active_call->sent_initial_metadata = true; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - has_ops |= 1 << GRPC_OP_SEND_INITIAL_METADATA; - read_metadata(&inp, &op->data.send_initial_metadata.count, - &op->data.send_initial_metadata.metadata, - g_active_call); - } - break; - case GRPC_OP_SEND_MESSAGE: - op->op = GRPC_OP_SEND_MESSAGE; - if (g_active_call->send_message != nullptr) { - ok = false; - } else { - has_ops |= 1 << GRPC_OP_SEND_MESSAGE; - g_active_call->send_message = - op->data.send_message.send_message = read_message(&inp); - } - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - has_ops |= 1 << GRPC_OP_SEND_CLOSE_FROM_CLIENT; - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - has_ops |= 1 << 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, - g_active_call); - op->data.send_status_from_server.status = - static_cast( - grpc_fuzzer_get_next_byte(&inp)); - op->data.send_status_from_server.status_details = - add_slice_to_unref(g_active_call, - read_buffer_like_slice(&inp)); - break; - case GRPC_OP_RECV_INITIAL_METADATA: - op->op = GRPC_OP_RECV_INITIAL_METADATA; - has_ops |= 1 << GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &g_active_call->recv_initial_metadata; - break; - case GRPC_OP_RECV_MESSAGE: - if (g_active_call->done_flags & DONE_FLAG_CALL_CLOSED) { - ok = false; - } else { - op->op = GRPC_OP_RECV_MESSAGE; - has_ops |= 1 << GRPC_OP_RECV_MESSAGE; - op->data.recv_message.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 = &g_active_call->status; - op->data.recv_status_on_client.trailing_metadata = - &g_active_call->recv_trailing_metadata; - op->data.recv_status_on_client.status_details = - &g_active_call->recv_status_details; - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - has_ops |= 1 << GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = - &g_active_call->cancelled; - break; - } - op->reserved = nullptr; - op->flags = grpc_fuzzer_get_next_uint32(&inp); - } - if (g_channel == nullptr) ok = false; - if (ok) { - validator* v = make_finished_batch_validator(g_active_call, has_ops); - g_active_call->pending_ops++; - grpc_call_error error = grpc_call_start_batch( - g_active_call->call, ops, num_ops, v, nullptr); - if (error != GRPC_CALL_OK) { - v->validate(v->arg, false); - gpr_free(v); - } - } else { - end(&inp); - } - if (!ok && (has_ops & (1 << GRPC_OP_SEND_MESSAGE))) { - grpc_byte_buffer_destroy(g_active_call->send_message); - g_active_call->send_message = nullptr; - } - gpr_free(ops); - - break; - } - // cancel current call - case 13: { - if (g_active_call->type != ROOT && g_active_call->call != nullptr) { - grpc_call_cancel(g_active_call->call, nullptr); - } else { - end(&inp); - } - break; - } - // get a calls peer - case 14: { - if (g_active_call->type != ROOT && g_active_call->call != nullptr) { - free_non_null(grpc_call_get_peer(g_active_call->call)); - } else { - end(&inp); - } - break; - } - // get a channels target - case 15: { - if (g_channel != nullptr) { - free_non_null(grpc_channel_get_target(g_channel)); - } else { - end(&inp); - } - break; - } - // send a ping on a channel - case 16: { - if (g_channel != nullptr) { - pending_pings++; - grpc_channel_ping(g_channel, cq, - create_validator(decrement, &pending_pings), - nullptr); - } else { - end(&inp); - } - break; - } - // enable a tracer - case 17: { - char* tracer = grpc_fuzzer_get_next_string(&inp, nullptr); - grpc_tracer_set_enabled(tracer, 1); - gpr_free(tracer); - break; - } - // disable a tracer - case 18: { - char* tracer = grpc_fuzzer_get_next_string(&inp, nullptr); - grpc_tracer_set_enabled(tracer, 0); - gpr_free(tracer); - break; - } - // request a server call - case 19: { - if (g_server == nullptr) { - end(&inp); - break; - } - 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); - if (error != GRPC_CALL_OK) { - v->validate(v->arg, false); - gpr_free(v); - } - break; - } - // destroy a call - case 20: { - if (g_active_call->type != ROOT && - g_active_call->type != PENDING_SERVER && - g_active_call->call != nullptr) { - destroy_call(g_active_call); - } else { - end(&inp); - } - break; - } - // resize the buffer pool - case 21: { - grpc_resource_quota_resize(g_resource_quota, read_uint22(&inp)); - break; - } - // create a secure channel - case 22: { - if (g_channel == nullptr) { - char* target = grpc_fuzzer_get_next_string(&inp, nullptr); - char* target_uri; - gpr_asprintf(&target_uri, "dns:%s", target); - grpc_channel_args* args = read_args(&inp); - grpc_channel_credentials* creds = read_channel_creds(&inp); - g_channel = - grpc_secure_channel_create(creds, target_uri, args, nullptr); - GPR_ASSERT(g_channel != nullptr); - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(args); - } - gpr_free(target_uri); - gpr_free(target); - grpc_channel_credentials_release(creds); - } else { - end(&inp); - } - break; - } - } - } - - GPR_ASSERT(g_channel == nullptr); - GPR_ASSERT(g_server == nullptr); - 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( - grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), nullptr) - .type == GRPC_QUEUE_SHUTDOWN); - grpc_completion_queue_destroy(cq); - - grpc_resource_quota_unref(g_resource_quota); - - grpc_shutdown_blocking(); - return 0; -}