diff options
author | 2015-02-18 14:16:15 -0800 | |
---|---|---|
committer | 2015-02-18 14:16:15 -0800 | |
commit | 9be83eec1de2932946d61b774788ca18fb41e2fe (patch) | |
tree | f8672252e92ceff39ee7eccc571c31a33cf548eb /src/core/transport/metadata.c | |
parent | efad8fadd36899ff98ff616c349d181f2f1e4004 (diff) |
Fix use-after-free.
Transport and channel have different lifetimes, but share a metadata
context.
Make the metadata context ref counted, and have transport take a ref.
Diffstat (limited to 'src/core/transport/metadata.c')
-rw-r--r-- | src/core/transport/metadata.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c index 3dc23e7de2..1c15716fad 100644 --- a/src/core/transport/metadata.c +++ b/src/core/transport/metadata.c @@ -79,7 +79,7 @@ typedef struct internal_metadata { struct grpc_mdctx { gpr_uint32 hash_seed; - int orphaned; + int refs; gpr_mu mu; @@ -114,7 +114,7 @@ static void unlock(grpc_mdctx *ctx) { mdelems on every unlock (instead of the usual 'I'm too loaded' trigger case), since otherwise we can be stuck waiting for a garbage collection that will never happen. */ - if (ctx->orphaned) { + if (ctx->refs == 0) { /* uncomment if you're having trouble diagnosing an mdelem leak to make things clearer (slows down destruction a lot, however) */ /* gc_mdtab(ctx); */ @@ -139,7 +139,7 @@ static void ref_md(internal_metadata *md) { grpc_mdctx *grpc_mdctx_create_with_seed(gpr_uint32 seed) { grpc_mdctx *ctx = gpr_malloc(sizeof(grpc_mdctx)); - ctx->orphaned = 0; + ctx->refs = 1; ctx->hash_seed = seed; gpr_mu_init(&ctx->mu); ctx->strtab = gpr_malloc(sizeof(internal_string *) * INITIAL_STRTAB_CAPACITY); @@ -197,10 +197,17 @@ static void metadata_context_destroy(grpc_mdctx *ctx) { gpr_free(ctx); } -void grpc_mdctx_orphan(grpc_mdctx *ctx) { +void grpc_mdctx_ref(grpc_mdctx *ctx) { lock(ctx); - GPR_ASSERT(!ctx->orphaned); - ctx->orphaned = 1; + GPR_ASSERT(ctx->refs > 0); + ctx->refs++; + unlock(ctx); +} + +void grpc_mdctx_unref(grpc_mdctx *ctx) { + lock(ctx); + GPR_ASSERT(ctx->refs > 0); + ctx->refs--; unlock(ctx); } |