From b2667416c21e0e9e829169404be4c04b4c973139 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Wed, 8 Nov 2017 11:19:56 +0000 Subject: [PATCH] rpcrt4: Don't free the argument if the freer was called, unless it's a simple ref. In the simple reference case the freer will not see the top-level pointer, so we need to free that here. This fixes a double-free caused by commit 614afcefa33c727f31d566c3d7ee05d74afc363f. Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/rpcrt4/ndr_stubless.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/dlls/rpcrt4/ndr_stubless.c b/dlls/rpcrt4/ndr_stubless.c index f65eaf59178..f84c61751a5 100644 --- a/dlls/rpcrt4/ndr_stubless.c +++ b/dlls/rpcrt4/ndr_stubless.c @@ -1137,6 +1137,11 @@ LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, uns } #endif +static inline BOOL param_needs_alloc( PARAM_ATTRIBUTES attr ) +{ + return attr.IsOut && !attr.IsIn && !attr.IsBasetype && !attr.IsByValue; +} + static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, enum stubless_phase phase, unsigned short number_of_params) @@ -1172,20 +1177,14 @@ static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, { HeapFree(GetProcessHeap(), 0, *(void **)pArg); } - else if (params[i].attr.IsOut && - !params[i].attr.IsIn && - !params[i].attr.IsBasetype && - !params[i].attr.IsByValue) + else if (param_needs_alloc(params[i].attr) && + (!params[i].attr.MustFree || params[i].attr.IsSimpleRef)) { if (*pTypeFormat != RPC_FC_BIND_CONTEXT) pStubMsg->pfnFree(*(void **)pArg); } break; case STUBLESS_INITOUT: - if (!params[i].attr.IsIn && - params[i].attr.IsOut && - !params[i].attr.IsBasetype && - !params[i].attr.ServerAllocSize && - !params[i].attr.IsByValue) + if (param_needs_alloc(params[i].attr) && !params[i].attr.ServerAllocSize) { if (*pTypeFormat == RPC_FC_BIND_CONTEXT) {