aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/core/end2end/fuzzers/api_fuzzer.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/core/end2end/fuzzers/api_fuzzer.c')
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer.c226
1 files changed, 202 insertions, 24 deletions
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index 4e19b76014..746134c85b 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -34,6 +34,7 @@
#include <string.h>
#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@@ -45,6 +46,7 @@
#include "src/core/lib/iomgr/timer.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/passthru_endpoint.h"
////////////////////////////////////////////////////////////////////////////////
@@ -56,6 +58,21 @@ 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);
+ return g_now;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// input_stream: allows easy access to input bytes, and allows reading a little
// past the end (avoiding needing to check everywhere)
@@ -137,10 +154,10 @@ static uint32_t read_uint32(input_stream *inp) {
}
static grpc_byte_buffer *read_message(input_stream *inp) {
- gpr_slice slice = gpr_slice_malloc(read_uint22(inp));
- memset(GPR_SLICE_START_PTR(slice), 0, GPR_SLICE_LENGTH(slice));
+ 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);
- gpr_slice_unref(slice);
+ grpc_slice_unref(slice);
return out;
}
@@ -150,13 +167,28 @@ static grpc_channel_args *read_args(input_stream *inp) {
size_t n = next_byte(inp);
grpc_arg *args = gpr_malloc(sizeof(*args) * n);
for (size_t i = 0; i < n; i++) {
- bool is_string = next_byte(inp) & 1;
- args[i].type = is_string ? GRPC_ARG_STRING : GRPC_ARG_INTEGER;
- args[i].key = read_string(inp);
- if (is_string) {
- args[i].value.string = read_string(inp);
- } else {
- args[i].value.integer = read_int(inp);
+ switch (next_byte(inp)) {
+ case 1:
+ args[i].type = GRPC_ARG_STRING;
+ args[i].key = read_string(inp);
+ args[i].value.string = read_string(inp);
+ break;
+ case 2:
+ args[i].type = GRPC_ARG_INTEGER;
+ args[i].key = read_string(inp);
+ 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 = gpr_malloc(sizeof(*a));
@@ -165,22 +197,138 @@ static grpc_channel_args *read_args(input_stream *inp) {
return a;
}
-static bool is_eof(input_stream *inp) { return inp->cur == inp->end; }
+typedef struct cred_artifact_ctx {
+ int num_release;
+ char *release[3];
+} cred_artifact_ctx;
+#define CRED_ARTIFACT_CTX_INIT \
+ { \
+ 0, { 0 } \
+ }
-////////////////////////////////////////////////////////////////////////////////
-// global state
+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 gpr_timespec g_now;
-static grpc_server *g_server;
-static grpc_channel *g_channel;
+static const char *read_cred_artifact(cred_artifact_ctx *ctx, input_stream *inp,
+ const char **builtins,
+ size_t num_builtins) {
+ uint8_t b = next_byte(inp);
+ if (b == 0) return NULL;
+ if (b == 1) return ctx->release[ctx->num_release++] = read_string(inp);
+ if (b >= num_builtins + 1) {
+ end(inp);
+ return NULL;
+ }
+ return builtins[b - 1];
+}
-extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
+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 != NULL && certs != NULL ? &key_cert_pair : NULL,
+ NULL);
+ cred_artifact_ctx_finish(&ctx);
+ return creds;
+}
-static gpr_timespec now_impl(gpr_clock_type clock_type) {
- GPR_ASSERT(clock_type != GPR_TIMESPAN);
- return g_now;
+static grpc_call_credentials *read_call_creds(input_stream *inp) {
+ switch (next_byte(inp)) {
+ default:
+ end(inp);
+ return NULL;
+ case 0:
+ return NULL;
+ case 1: {
+ grpc_call_credentials *c1 = read_call_creds(inp);
+ grpc_call_credentials *c2 = read_call_creds(inp);
+ if (c1 != NULL && c2 != NULL) {
+ grpc_call_credentials *out =
+ grpc_composite_call_credentials_create(c1, c2, NULL);
+ grpc_call_credentials_release(c1);
+ grpc_call_credentials_release(c2);
+ return out;
+ } else if (c1 != NULL) {
+ return c1;
+ } else if (c2 != NULL) {
+ return c2;
+ } else {
+ return NULL;
+ }
+ GPR_UNREACHABLE_CODE(return NULL);
+ }
+ case 2: {
+ cred_artifact_ctx ctx = CRED_ARTIFACT_CTX_INIT;
+ const char *access_token = read_cred_artifact(&ctx, inp, NULL, 0);
+ grpc_call_credentials *out =
+ access_token == NULL ? NULL : grpc_access_token_credentials_create(
+ access_token, NULL);
+ 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, NULL, 0);
+ const char *auth_selector = read_cred_artifact(&ctx, inp, NULL, 0);
+ grpc_call_credentials *out = auth_token == NULL || auth_selector == NULL
+ ? NULL
+ : grpc_google_iam_credentials_create(
+ auth_token, auth_selector, NULL);
+ cred_artifact_ctx_finish(&ctx);
+ return out;
+ }
+ /* TODO(ctiller): more cred types here */
+ }
}
+static grpc_channel_credentials *read_channel_creds(input_stream *inp) {
+ switch (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);
+ if (c1 != NULL && c2 != NULL) {
+ grpc_channel_credentials *out =
+ grpc_composite_channel_credentials_create(c1, c2, NULL);
+ 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 NULL;
+ } else {
+ return NULL;
+ }
+ GPR_UNREACHABLE_CODE(return NULL);
+ }
+ case 2:
+ return NULL;
+ default:
+ end(inp);
+ return NULL;
+ }
+}
+
+static bool is_eof(input_stream *inp) { return inp->cur == inp->end; }
+
////////////////////////////////////////////////////////////////////////////////
// dns resolution
@@ -213,7 +361,9 @@ static void finish_resolve(grpc_exec_ctx *exec_ctx, void *arg,
}
void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr,
- const char *default_port, grpc_closure *on_done,
+ const char *default_port,
+ grpc_pollset_set *interested_parties,
+ grpc_closure *on_done,
grpc_resolved_addresses **addresses) {
addr_req *r = gpr_malloc(sizeof(*r));
r->addr = gpr_strdup(addr);
@@ -231,8 +381,8 @@ void my_resolve_address(grpc_exec_ctx *exec_ctx, const char *addr,
// defined in tcp_client_posix.c
extern void (*grpc_tcp_client_connect_impl)(
grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
- grpc_pollset_set *interested_parties, const grpc_resolved_address *addr,
- gpr_timespec deadline);
+ grpc_pollset_set *interested_parties, const grpc_channel_args *channel_args,
+ const grpc_resolved_address *addr, gpr_timespec deadline);
static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_endpoint **ep, gpr_timespec deadline);
@@ -252,7 +402,7 @@ static void do_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
} else if (g_server != NULL) {
grpc_endpoint *client;
grpc_endpoint *server;
- grpc_passthru_endpoint_create(&client, &server);
+ grpc_passthru_endpoint_create(&client, &server, g_resource_quota);
*fc->ep = client;
grpc_transport *transport =
@@ -289,6 +439,7 @@ static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
static void my_tcp_client_connect(grpc_exec_ctx *exec_ctx,
grpc_closure *closure, grpc_endpoint **ep,
grpc_pollset_set *interested_parties,
+ const grpc_channel_args *channel_args,
const grpc_resolved_address *addr,
gpr_timespec deadline) {
sched_connect(exec_ctx, closure, ep, deadline);
@@ -520,6 +671,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
int pending_pings = 0;
g_active_call = new_call(NULL, ROOT);
+ g_resource_quota = grpc_resource_quota_create("api_fuzzer");
grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
@@ -939,6 +1091,30 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
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 == NULL) {
+ char *target = read_string(&inp);
+ 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, NULL);
+ GPR_ASSERT(g_channel != NULL);
+ grpc_channel_args_destroy(args);
+ gpr_free(target_uri);
+ gpr_free(target);
+ grpc_channel_credentials_release(creds);
+ } else {
+ end(&inp);
+ }
+ break;
+ }
}
}
@@ -954,6 +1130,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
.type == GRPC_QUEUE_SHUTDOWN);
grpc_completion_queue_destroy(cq);
+ grpc_resource_quota_unref(g_resource_quota);
+
grpc_shutdown();
return 0;
}