| 
					
				 | 
			
			
				@@ -0,0 +1,1206 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 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 <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> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#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<char*>(gpr_malloc(*length)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (size_t i = 0; i < *length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (*buffer)[i] = static_cast<char>(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<int>(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<grpc_arg*>(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<grpc_channel_args*>(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<grpc_core::ServerAddressList>* addresses; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} addr_req; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void finish_resolve(void* arg, grpc_error* error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addr_req* r = static_cast<addr_req*>(arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (error == GRPC_ERROR_NONE && 0 == strcmp(r->addr, "server")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (r->addrs != nullptr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_resolved_addresses* addrs = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          static_cast<grpc_resolved_addresses*>(gpr_malloc(sizeof(*addrs))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      addrs->naddrs = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      addrs->addrs = static_cast<grpc_resolved_address*>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          gpr_malloc(sizeof(*addrs->addrs))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      addrs->addrs[0].len = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      *r->addrs = addrs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if (r->addresses != nullptr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      *r->addresses = absl::make_unique<grpc_core::ServerAddressList>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      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<grpc_core::ServerAddressList>* addresses, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bool /*check_grpclb*/, char** /*service_config_json*/, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int /*query_timeout*/, grpc_core::Combiner* /*combiner*/) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addr_req* r = static_cast<addr_req*>(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<future_connect*>(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<future_connect*>(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<validator*>(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<int*>(counter); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void decrement(void* counter, bool /*success*/) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  --*static_cast<int*>(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<connectivity_watch*>(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<connectivity_watch*>(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<call_state*>(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<void**>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        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<grpc_slice**>(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<grpc_slice*>(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<grpc_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_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<grpc_metadata*>(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<call_state*>(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<batch_info*>(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<batch_info*>(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<validator*>(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<grpc_op*>(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_status_code>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                      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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |