diff options
author | 2017-01-20 11:02:11 -0500 | |
---|---|---|
committer | 2017-02-07 15:45:44 -0500 | |
commit | 5f3cfe960f708a397c4465a3064072dd3b2d7bb7 (patch) | |
tree | 363b85675839116c4314dbff8548170d94031acf /include/grpc++/impl/codegen/proto_utils.h | |
parent | 27ee9d015dff36ebf32e95c80a4d0b37ac7137ba (diff) |
Fix read from uninitialized memory bug in GrpcBufferWriter.
This commit fixes an issue in which the following sequence of operations
leads to use of uninitialized memory:
1. Caller invokes GrpcBufferWriter::Next(), and then makes use of 8191
bytes in the returned buffer (which is 8192 bytes in size).
2. Caller then returns the unused single byte via
GrpcBufferWriter::BackUp(). This method invokes
g_core_codegen_interface->grpc_slice_split_tail(), which causes
backup_slice_ to be a grpc_slice with one byte.
3. At the next invocation of GrpcBufferWriter::Next(), a reference to
the single byte grpc_slice is returned to the caller.
The problem here is that the returned reference is to the inlined buffer
in the grpc_slice, which is resident in slice_, not the location of the
buffer inside slice_buffer_ after
g_core_codegen_interface->grpc_slice_buffer_add() in
GrpcBufferWriter::Next(). As a result, any data the caller writes to the
returned void* data is lost.
The solution is to avoid inlined backup slices.
Diffstat (limited to 'include/grpc++/impl/codegen/proto_utils.h')
-rw-r--r-- | include/grpc++/impl/codegen/proto_utils.h | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h index 2123b62ed9..6df9de4fd2 100644 --- a/include/grpc++/impl/codegen/proto_utils.h +++ b/include/grpc++/impl/codegen/proto_utils.h @@ -50,6 +50,8 @@ extern CoreCodegenInterface* g_core_codegen_interface; namespace internal { +class GrpcBufferWriterPeer; + const int kGrpcBufferWriterMaxBufferLength = 8192; class GrpcBufferWriter final @@ -91,13 +93,18 @@ class GrpcBufferWriter final &slice_, GRPC_SLICE_LENGTH(slice_) - count); g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_); } - have_backup_ = true; + // It's dangerous to keep an inlined grpc_slice as the backup slice, since + // on a following Next() call, a reference will be returned to this slice + // via GRPC_SLICE_START_PTR, which will not be an adddress held by + // slice_buffer_. + have_backup_ = backup_slice_.refcount != NULL; byte_count_ -= count; } grpc::protobuf::int64 ByteCount() const override { return byte_count_; } private: + friend class GrpcBufferWriterPeer; const int block_size_; int64_t byte_count_; grpc_slice_buffer* slice_buffer_; |