Copy slices for in-process transports: its no longer safe to just ref
diff --git a/include/grpc/slice.h b/include/grpc/slice.h
index 039347f..9c4b158 100644
--- a/include/grpc/slice.h
+++ b/include/grpc/slice.h
@@ -53,6 +53,9 @@
    where dest!=NULL , then (*dest)(start, len).  Requires s initialized.  */
 GPRAPI void grpc_slice_unref(grpc_slice s);
 
+/* Copy slice - create a new slice that contains the same data as s */
+GPRAPI grpc_slice grpc_slice_copy(grpc_slice s);
+
 /* Create a slice pointing at some data. Calls malloc to allocate a refcount
    for the object, and arranges that destroy will be called with the pointer
    passed in at destruction. */
diff --git a/src/core/lib/slice/slice.c b/src/core/lib/slice/slice.c
index 9e69b44..b90738f 100644
--- a/src/core/lib/slice/slice.c
+++ b/src/core/lib/slice/slice.c
@@ -55,6 +55,13 @@
   return out;
 }
 
+grpc_slice grpc_slice_copy(grpc_slice s) {
+  grpc_slice out = GRPC_SLICE_MALLOC(GRPC_SLICE_LENGTH(s));
+  memcpy(GRPC_SLICE_START_PTR(out), GRPC_SLICE_START_PTR(s),
+         GRPC_SLICE_LENGTH(s));
+  return out;
+}
+
 grpc_slice grpc_slice_ref_internal(grpc_slice slice) {
   if (slice.refcount) {
     slice.refcount->vtable->ref(slice.refcount);
diff --git a/test/core/util/passthru_endpoint.c b/test/core/util/passthru_endpoint.c
index 121567f..ad718c7 100644
--- a/test/core/util/passthru_endpoint.c
+++ b/test/core/util/passthru_endpoint.c
@@ -102,13 +102,13 @@
     error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Endpoint already shutdown");
   } else if (m->on_read != NULL) {
     for (size_t i = 0; i < slices->count; i++) {
-      grpc_slice_buffer_add(m->on_read_out, grpc_slice_ref(slices->slices[i]));
+      grpc_slice_buffer_add(m->on_read_out, grpc_slice_copy(slices->slices[i]));
     }
     grpc_closure_sched(exec_ctx, m->on_read, GRPC_ERROR_NONE);
     m->on_read = NULL;
   } else {
     for (size_t i = 0; i < slices->count; i++) {
-      grpc_slice_buffer_add(&m->read_buffer, grpc_slice_ref(slices->slices[i]));
+      grpc_slice_buffer_add(&m->read_buffer, grpc_slice_copy(slices->slices[i]));
     }
   }
   gpr_mu_unlock(&m->parent->mu);
diff --git a/test/core/util/trickle_endpoint.c b/test/core/util/trickle_endpoint.c
index 0848147..66f30c8 100644
--- a/test/core/util/trickle_endpoint.c
+++ b/test/core/util/trickle_endpoint.c
@@ -66,14 +66,13 @@
 static void te_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
                      grpc_slice_buffer *slices, grpc_closure *cb) {
   trickle_endpoint *te = (trickle_endpoint *)ep;
-  for (size_t i = 0; i < slices->count; i++) {
-    grpc_slice_ref_internal(slices->slices[i]);
-  }
   gpr_mu_lock(&te->mu);
   if (te->write_buffer.length == 0) {
     te->last_write = gpr_now(GPR_CLOCK_MONOTONIC);
   }
-  grpc_slice_buffer_addn(&te->write_buffer, slices->slices, slices->count);
+  for (size_t i = 0; i < slices->count; i++) {
+    grpc_slice_buffer_add(&te->write_buffer, grpc_slice_copy(slices->slices[i]));
+  }
   grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_REF(te->error));
   gpr_mu_unlock(&te->mu);
 }