Skip to content

Commit fcb8ab3

Browse files
kevintsMrMage
authored andcommitted
Improve memory management in Channel (#368)
* Improve memory management in Channel * Use the gpr family of allocation functions instead of malloc/free (as these cannot return `NULL`). * Explicitly extend lifetime of `argumentWrappers` - Swift doesn't guarantee that objects will live to the end of their scope, so the optimizer is free to call Channel.Argument.Wrapper.deinit before the call to cgrpc_channel_create_secure, which would result in a use-after-free. * Also use gpr_free to free cgrpc_calls * Fix imports in call.c
1 parent 99d3834 commit fcb8ab3

File tree

3 files changed

+24
-22
lines changed

3 files changed

+24
-22
lines changed

Sources/CgRPC/shim/call.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
#include "internal.h"
1717
#include "cgrpc.h"
1818

19+
#include <grpc/support/alloc.h>
20+
1921
#include <stdlib.h>
20-
#include <string.h>
21-
#include <assert.h>
2222

2323
void cgrpc_call_destroy(cgrpc_call *call) {
2424
if (call->call) {
2525
grpc_call_unref(call->call);
2626
}
27-
free(call);
27+
gpr_free(call);
2828
}
2929

3030
grpc_call_error cgrpc_call_perform(cgrpc_call *call, cgrpc_operations *operations, void *tag) {

Sources/CgRPC/shim/channel.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,12 @@
1818
#include <grpc/support/string_util.h>
1919
#include <grpc/support/alloc.h>
2020

21-
#include <assert.h>
22-
#include <stdio.h>
2321
#include <stdlib.h>
24-
#include <string.h>
2522

2623
cgrpc_channel *cgrpc_channel_create(const char *address,
2724
grpc_arg *args,
2825
int num_args) {
29-
cgrpc_channel *c = (cgrpc_channel *) malloc(sizeof (cgrpc_channel));
26+
cgrpc_channel *c = (cgrpc_channel *) gpr_zalloc(sizeof (cgrpc_channel));
3027

3128
grpc_channel_args channel_args;
3229
channel_args.args = args;
@@ -43,7 +40,7 @@ cgrpc_channel *cgrpc_channel_create_secure(const char *address,
4340
const char *client_private_key,
4441
grpc_arg *args,
4542
int num_args) {
46-
cgrpc_channel *c = (cgrpc_channel *) malloc(sizeof (cgrpc_channel));
43+
cgrpc_channel *c = (cgrpc_channel *) gpr_zalloc(sizeof (cgrpc_channel));
4744

4845
grpc_channel_args channel_args;
4946
channel_args.args = args;
@@ -66,7 +63,7 @@ cgrpc_channel *cgrpc_channel_create_secure(const char *address,
6663
cgrpc_channel *cgrpc_channel_create_google(const char *address,
6764
grpc_arg *args,
6865
int num_args) {
69-
cgrpc_channel *c = (cgrpc_channel *) malloc(sizeof (cgrpc_channel));
66+
cgrpc_channel *c = (cgrpc_channel *) gpr_zalloc(sizeof (cgrpc_channel));
7067

7168
grpc_channel_args channel_args;
7269
channel_args.args = args;
@@ -83,7 +80,7 @@ cgrpc_channel *cgrpc_channel_create_google(const char *address,
8380
void cgrpc_channel_destroy(cgrpc_channel *c) {
8481
grpc_channel_destroy(c->channel);
8582
c->channel = NULL;
86-
free(c);
83+
gpr_free(c);
8784
}
8885

8986
cgrpc_call *cgrpc_channel_create_call(cgrpc_channel *channel,
@@ -105,8 +102,7 @@ cgrpc_call *cgrpc_channel_create_call(cgrpc_channel *channel,
105102
NULL);
106103
grpc_slice_unref(host_slice);
107104
grpc_slice_unref(method_slice);
108-
cgrpc_call *call = (cgrpc_call *) malloc(sizeof(cgrpc_call));
109-
memset(call, 0, sizeof(cgrpc_call));
105+
cgrpc_call *call = (cgrpc_call *) gpr_zalloc(sizeof(cgrpc_call));
110106
call->call = channel_call;
111107
return call;
112108
}

Sources/SwiftGRPC/Core/Channel.swift

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ public class Channel {
4545
gRPC.initialize()
4646
host = address
4747
let argumentWrappers = arguments.map { $0.toCArg() }
48-
var argumentValues = argumentWrappers.map { $0.wrapped }
4948

50-
if secure {
51-
underlyingChannel = cgrpc_channel_create_secure(address, roots_pem(), nil, nil, &argumentValues, Int32(arguments.count))
52-
} else {
53-
underlyingChannel = cgrpc_channel_create(address, &argumentValues, Int32(arguments.count))
49+
underlyingChannel = withExtendedLifetime(argumentWrappers) {
50+
var argumentValues = argumentWrappers.map { $0.wrapped }
51+
if secure {
52+
return cgrpc_channel_create_secure(address, roots_pem(), nil, nil, &argumentValues, Int32(arguments.count))
53+
} else {
54+
return cgrpc_channel_create(address, &argumentValues, Int32(arguments.count))
55+
}
5456
}
5557
completionQueue = CompletionQueue(underlyingCompletionQueue: cgrpc_channel_completion_queue(underlyingChannel), name: "Client")
5658
completionQueue.run() // start a loop that watches the channel's completion queue
@@ -64,9 +66,11 @@ public class Channel {
6466
gRPC.initialize()
6567
host = googleAddress
6668
let argumentWrappers = arguments.map { $0.toCArg() }
67-
var argumentValues = argumentWrappers.map { $0.wrapped }
68-
69-
underlyingChannel = cgrpc_channel_create_google(googleAddress, &argumentValues, Int32(arguments.count))
69+
70+
underlyingChannel = withExtendedLifetime(argumentWrappers) {
71+
var argumentValues = argumentWrappers.map { $0.wrapped }
72+
return cgrpc_channel_create_google(googleAddress, &argumentValues, Int32(arguments.count))
73+
}
7074

7175
completionQueue = CompletionQueue(underlyingCompletionQueue: cgrpc_channel_completion_queue(underlyingChannel), name: "Client")
7276
completionQueue.run() // start a loop that watches the channel's completion queue
@@ -83,9 +87,11 @@ public class Channel {
8387
gRPC.initialize()
8488
host = address
8589
let argumentWrappers = arguments.map { $0.toCArg() }
86-
var argumentValues = argumentWrappers.map { $0.wrapped }
8790

88-
underlyingChannel = cgrpc_channel_create_secure(address, certificates, clientCertificates, clientKey, &argumentValues, Int32(arguments.count))
91+
underlyingChannel = withExtendedLifetime(argumentWrappers) {
92+
var argumentValues = argumentWrappers.map { $0.wrapped }
93+
return cgrpc_channel_create_secure(address, certificates, clientCertificates, clientKey, &argumentValues, Int32(arguments.count))
94+
}
8995
completionQueue = CompletionQueue(underlyingCompletionQueue: cgrpc_channel_completion_queue(underlyingChannel), name: "Client")
9096
completionQueue.run() // start a loop that watches the channel's completion queue
9197
}

0 commit comments

Comments
 (0)