From d99a925d52b9b56306c245b3e4d43e7a737dfe35 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Tue, 28 Jun 2016 13:06:43 -0700 Subject: [PATCH] fix for working with compressed data. Fixes #6746. Using correct API that gives length of uncompressed data so correct amount of memory is allocated. --- .../GRPCClient/private/NSData+GRPC.m | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/objective-c/GRPCClient/private/NSData+GRPC.m b/src/objective-c/GRPCClient/private/NSData+GRPC.m index e6a6c3c605a..6b635a6649b 100644 --- a/src/objective-c/GRPCClient/private/NSData+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSData+GRPC.m @@ -39,17 +39,19 @@ // TODO(jcanizales): Move these two incantations to the C library. -static void CopyByteBufferToCharArray(grpc_byte_buffer *buffer, char *array) { - size_t offset = 0; +static void MallocAndCopyByteBufferToCharArray(grpc_byte_buffer *buffer, + size_t *length, char **array) { grpc_byte_buffer_reader reader; grpc_byte_buffer_reader_init(&reader, buffer); - gpr_slice next; - while (grpc_byte_buffer_reader_next(&reader, &next) != 0){ - memcpy(array + offset, GPR_SLICE_START_PTR(next), - (size_t)GPR_SLICE_LENGTH(next)); - offset += GPR_SLICE_LENGTH(next); - gpr_slice_unref(next); + gpr_slice slice = grpc_byte_buffer_reader_readall(&reader); + size_t uncompressed_length = GPR_SLICE_LENGTH(slice); + char *result = malloc(uncompressed_length); + if (result) { + memcpy(result, GPR_SLICE_START_PTR(slice), uncompressed_length); } + gpr_slice_unref(slice); + *array = result; + *length = uncompressed_length; } static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, @@ -65,8 +67,9 @@ static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, if (buffer == NULL) { return nil; } - NSUInteger length = grpc_byte_buffer_length(buffer); - char *array = malloc(length * sizeof(*array)); + char *array; + NSUInteger length; + MallocAndCopyByteBufferToCharArray(buffer, &length, &array); if (!array) { // TODO(jcanizales): grpc_byte_buffer is reference-counted, so we can // prevent this memory problem by implementing a subclass of NSData @@ -74,7 +77,6 @@ static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, // can be implemented using a grpc_byte_buffer_reader. return nil; } - CopyByteBufferToCharArray(buffer, array); return [self dataWithBytesNoCopy:array length:length freeWhenDone:YES]; } @@ -85,8 +87,10 @@ static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, // The following implementation is thus not optimal, sometimes requiring two // copies (one by self.bytes and another by gpr_slice_from_copied_buffer). // If it turns out to be an issue, we can use enumerateByteRangesUsingblock: - // to create an array of gpr_slice objects to pass to grpc_raw_byte_buffer_create. + // to create an array of gpr_slice objects to pass to + // grpc_raw_byte_buffer_create. // That would make it do exactly one copy, always. - return CopyCharArrayToNewByteBuffer((const char *)self.bytes, (size_t)self.length); + return CopyCharArrayToNewByteBuffer((const char *)self.bytes, + (size_t)self.length); } @end