Api fuzzer double free bug (#28237)
* Updating surface/call implementation to handle double free exception if there is an error in enqueuing batches of operations
* Adding double free exception inducing testcase
diff --git a/src/core/lib/slice/slice_buffer.cc b/src/core/lib/slice/slice_buffer.cc
index d461fe6..12cca86 100644
--- a/src/core/lib/slice/slice_buffer.cc
+++ b/src/core/lib/slice/slice_buffer.cc
@@ -84,6 +84,10 @@
grpc_slice_buffer_reset_and_unref_internal(sb);
if (sb->base_slices != sb->inlined) {
gpr_free(sb->base_slices);
+ // As a precaution, set sb->base_slices to equal sb->inlined
+ // to prevent a double free attempt if grpc_slice_buffer_destroy_internal
+ // is invoked two times on the same slice buffer.
+ sb->base_slices = sb->slices = sb->inlined;
}
}
diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc
index bb5a115..9102f46 100644
--- a/src/core/lib/surface/call.cc
+++ b/src/core/lib/surface/call.cc
@@ -1963,7 +1963,9 @@
}
if (stream_op->send_message) {
call->sending_message = false;
- call->sending_stream->Orphan();
+ // No need to invoke call->sending_stream->Orphan() explicitly.
+ // stream_op_payload->send_message.send_message.reset() calls Deletor
+ // of call->sending_stream which in-turn invokes the Orphan() method.
stream_op_payload->send_message.send_message.reset();
}
if (stream_op->send_trailing_metadata) {
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-5404970078044160 b/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-5404970078044160
new file mode 100644
index 0000000..d7dc5f4
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/testcase-5404970078044160
@@ -0,0 +1,57 @@
+actions {
+ create_channel {
+ target: "unix:"
+ channel_actions {
+ add_n_bytes_writable: 10
+ add_n_bytes_readable: 1000002
+ }
+ }
+}
+actions {
+ create_call {
+ method {
+ value: "0"
+ }
+ timeout: 869738192
+ }
+}
+actions {
+ queue_batch {
+ operations {
+ send_message {
+ message {
+ intern: true
+ }
+ message {
+ intern: true
+ }
+ message {
+ intern: true
+ }
+ message {
+ }
+ message {
+ intern: true
+ }
+ message {
+ }
+ message {
+ value: "Z"
+ intern: true
+ }
+ message {
+ intern: true
+ }
+ message {
+ value: "http"
+ intern: true
+ }
+ }
+ }
+ operations {
+ receive_message {
+ }
+ flags: 11008
+ }
+ }
+}