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.c111
1 files changed, 83 insertions, 28 deletions
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index 200a51858a..30d814b01b 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -44,6 +44,7 @@
#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/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"
@@ -90,7 +91,7 @@ static uint8_t next_byte(input_stream *inp) {
static void end(input_stream *inp) { inp->cur = inp->end; }
-static char *read_string(input_stream *inp) {
+static char *read_string(input_stream *inp, bool *special) {
char *str = NULL;
size_t cap = 0;
size_t sz = 0;
@@ -102,18 +103,56 @@ static char *read_string(input_stream *inp) {
}
c = (char)next_byte(inp);
str[sz++] = c;
- } while (c != 0);
+ } while (c != 0 && c != 1);
+ if (special != NULL) {
+ *special = (c == 1);
+ }
+ if (c == 1) {
+ str[sz - 1] = 0;
+ }
return str;
}
-static void read_buffer(input_stream *inp, char **buffer, size_t *length) {
+static void read_buffer(input_stream *inp, char **buffer, size_t *length,
+ bool *special) {
*length = next_byte(inp);
+ if (*length == 255) {
+ if (special != NULL) *special = true;
+ *length = next_byte(inp);
+ } else {
+ if (special != NULL) *special = false;
+ }
*buffer = gpr_malloc(*length);
for (size_t i = 0; i < *length; i++) {
(*buffer)[i] = (char)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 = read_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 = next_byte(inp);
uint32_t x = b & 0x7f;
@@ -170,12 +209,12 @@ static grpc_channel_args *read_args(input_stream *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);
+ args[i].key = read_string(inp, NULL);
+ args[i].value.string = read_string(inp, NULL);
break;
case 2:
args[i].type = GRPC_ARG_INTEGER;
- args[i].key = read_string(inp);
+ args[i].key = read_string(inp, NULL);
args[i].value.integer = read_int(inp);
break;
case 3:
@@ -217,7 +256,7 @@ static const char *read_cred_artifact(cred_artifact_ctx *ctx, input_stream *inp,
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 == 1) return ctx->release[ctx->num_release++] = read_string(inp, NULL);
if (b >= num_builtins + 1) {
end(inp);
return NULL;
@@ -508,8 +547,7 @@ typedef struct call_state {
grpc_status_code status;
grpc_metadata_array recv_initial_metadata;
grpc_metadata_array recv_trailing_metadata;
- char *recv_status_details;
- size_t recv_status_details_capacity;
+ grpc_slice recv_status_details;
int cancelled;
int pending_ops;
grpc_call_details call_details;
@@ -523,6 +561,11 @@ typedef struct call_state {
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;
@@ -558,12 +601,15 @@ static call_state *maybe_delete_call_state(call_state *call) {
call->next->prev = call->prev;
grpc_metadata_array_destroy(&call->recv_initial_metadata);
grpc_metadata_array_destroy(&call->recv_trailing_metadata);
- gpr_free(call->recv_status_details);
+ grpc_slice_unref(call->recv_status_details);
grpc_call_details_destroy(&call->call_details);
for (size_t i = 0; i < call->num_to_free; i++) {
gpr_free(call->to_free[i]);
}
+ for (size_t i = 0; i < call->num_slices_to_unref; i++) {
+ grpc_slice_unref(call->slices_to_unref[i]);
+ }
gpr_free(call->to_free);
gpr_free(call);
@@ -580,6 +626,17 @@ static void add_to_free(call_state *call, void *p) {
call->to_free[call->num_to_free++] = p;
}
+static grpc_slice *add_to_slice_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 =
+ gpr_realloc(call->slices_to_unref,
+ sizeof(*call->slices_to_unref) * call->cap_slices_to_unref);
+ }
+ call->slices_to_unref[call->num_to_free++] = s;
+ return &call->slices_to_unref[call->num_to_free - 1];
+}
+
static void read_metadata(input_stream *inp, size_t *count,
grpc_metadata **metadata, call_state *cs) {
*count = next_byte(inp);
@@ -587,12 +644,11 @@ static void read_metadata(input_stream *inp, size_t *count,
*metadata = gpr_malloc(*count * sizeof(**metadata));
memset(*metadata, 0, *count * sizeof(**metadata));
for (size_t i = 0; i < *count; i++) {
- (*metadata)[i].key = read_string(inp);
- read_buffer(inp, (char **)&(*metadata)[i].value,
- &(*metadata)[i].value_length);
+ (*metadata)[i].key = read_string_like_slice(inp);
+ (*metadata)[i].value = read_buffer_like_slice(inp);
(*metadata)[i].flags = read_uint32(inp);
- add_to_free(cs, (void *)(*metadata)[i].key);
- add_to_free(cs, (void *)(*metadata)[i].value);
+ add_to_slice_unref(cs, (*metadata)[i].key);
+ add_to_slice_unref(cs, (*metadata)[i].value);
}
} else {
*metadata = gpr_malloc(1);
@@ -656,7 +712,7 @@ static validator *make_finished_batch_validator(call_state *cs,
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- grpc_test_only_set_metadata_hash_seed(0);
+ grpc_test_only_set_slice_hash_seed(0);
if (squelch) gpr_set_log_function(dont_log);
input_stream inp = {data, data + size};
grpc_resolve_address = my_resolve_address;
@@ -742,7 +798,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// create an insecure channel
case 2: {
if (g_channel == NULL) {
- char *target = read_string(&inp);
+ char *target = read_string(&inp, NULL);
char *target_uri;
gpr_asprintf(&target_uri, "dns:%s", target);
grpc_channel_args *args = read_args(&inp);
@@ -871,8 +927,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
parent_call = g_active_call->call;
}
uint32_t propagation_mask = read_uint32(&inp);
- char *method = read_string(&inp);
- char *host = read_string(&inp);
+ grpc_slice method = read_string_like_slice(&inp);
+ grpc_slice host = read_string_like_slice(&inp);
gpr_timespec deadline =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
@@ -881,12 +937,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
call_state *cs = new_call(g_active_call, CLIENT);
cs->call =
grpc_channel_create_call(g_channel, parent_call, propagation_mask,
- cq, method, host, deadline, NULL);
+ cq, method, &host, deadline, NULL);
} else {
end(&inp);
}
- gpr_free(method);
- gpr_free(host);
+ grpc_slice_unref(method);
+ grpc_slice_unref(host);
break;
}
// switch the 'current' call
@@ -951,7 +1007,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
g_active_call);
op->data.send_status_from_server.status = next_byte(&inp);
op->data.send_status_from_server.status_details =
- read_string(&inp);
+ add_to_slice_unref(g_active_call,
+ read_buffer_like_slice(&inp));
break;
case GRPC_OP_RECV_INITIAL_METADATA:
op->op = GRPC_OP_RECV_INITIAL_METADATA;
@@ -971,8 +1028,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
&g_active_call->recv_trailing_metadata;
op->data.recv_status_on_client.status_details =
&g_active_call->recv_status_details;
- op->data.recv_status_on_client.status_details_capacity =
- &g_active_call->recv_status_details_capacity;
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
@@ -1060,14 +1115,14 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
// enable a tracer
case 17: {
- char *tracer = read_string(&inp);
+ char *tracer = read_string(&inp, NULL);
grpc_tracer_set_enabled(tracer, 1);
gpr_free(tracer);
break;
}
// disable a tracer
case 18: {
- char *tracer = read_string(&inp);
+ char *tracer = read_string(&inp, NULL);
grpc_tracer_set_enabled(tracer, 0);
gpr_free(tracer);
break;
@@ -1109,7 +1164,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// create a secure channel
case 22: {
if (g_channel == NULL) {
- char *target = read_string(&inp);
+ char *target = read_string(&inp, NULL);
char *target_uri;
gpr_asprintf(&target_uri, "dns:%s", target);
grpc_channel_args *args = read_args(&inp);