1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

rpcrt4: Add a refcount owned by MIDL_STUB_MESSAGE.

In cases where this could have been use-after-free, exceptions were
caught/hidden by RpcTryFinally, but still lead to leaks since
NdrProxyFreeBuffer wasn't able to call IRPCChannelBuffer::FreeBuffer.

StdProxy_GetChannel() now AddRef() on its return value (used to set
__proxy_frame::_StubMsg::pRpcChannelBuffer), and NdrProxyFreeBuffer()
calls the corresponding Release() and clears the now-weak pointer.
This makes the behavior of these function match the observed test
results, and fixes the crash/leak when a proxy is released mid-Invoke.
This commit is contained in:
Kevin Puetz 2022-10-10 23:31:08 +00:00 committed by Alexandre Julliard
parent 59f39b325d
commit a7be4256f6
2 changed files with 9 additions and 4 deletions

View file

@ -454,6 +454,9 @@ static void StdProxy_GetChannel(LPVOID iface,
StdProxyImpl *This = impl_from_proxy_obj( iface );
TRACE("(%p)->GetChannel(%p) %s\n",This,ppChannel,This->name);
if(This->pChannel)
IRpcChannelBuffer_AddRef(This->pChannel);
*ppChannel = This->pChannel;
}
@ -585,6 +588,8 @@ void WINAPI NdrProxyFreeBuffer(void *This,
(RPCOLEMESSAGE*)pStubMsg->RpcMsg);
pStubMsg->fBufferValid = TRUE;
}
IRpcChannelBuffer_Release(pStubMsg->pRpcChannelBuffer);
pStubMsg->pRpcChannelBuffer = NULL;
}
/***********************************************************************

View file

@ -1527,7 +1527,7 @@ static void test_ChannelBufferRefCount(IPSFactoryBuffer *ppsf)
NdrProxyInitialize(proxy_if1, &rpcMessage, &stubMessage, &stubDesc, 0);
/* stubMessage should add its own refcount on test_chanbuf */
todo_wine ok(test_chanbuf.RefCount == 2, "got %ld\n", test_chanbuf.RefCount);
ok(test_chanbuf.RefCount == 2, "got %ld\n", test_chanbuf.RefCount);
ok(stubMessage.pRpcChannelBuffer != NULL, "NULL pRocChannelBuffer\n");
/* stubMessage doesn't add its own refcounts on proxy_if1 or proxy_buffer,
@ -1536,17 +1536,17 @@ static void test_ChannelBufferRefCount(IPSFactoryBuffer *ppsf)
* this unadvise could be reentrant to Invoke because SendReceive pumps STA messages.
* The source would then erase that conection point entry and Release the proxy. */
IRpcProxyBuffer_Disconnect(proxy_buffer);
todo_wine ok(test_chanbuf.RefCount == 1, "got %ld\n", test_chanbuf.RefCount);
ok(test_chanbuf.RefCount == 1, "got %ld\n", test_chanbuf.RefCount);
IRpcProxyBuffer_Release(proxy_buffer);
refs = IUnknown_Release(proxy_if1);
ok(refs == 0, "got %ld\n", refs);
todo_wine ok(test_chanbuf.RefCount == 1, "got %ld\n", test_chanbuf.RefCount);
ok(test_chanbuf.RefCount == 1, "got %ld\n", test_chanbuf.RefCount);
/* NdrProxyFreeBuffer must not dereference the the now-freed proxy_if1,
* yet should still free the remaining reference on test_chanbuf */
NdrProxyFreeBuffer(proxy_if1, &stubMessage);
ok(test_chanbuf.RefCount == 0, "got %ld\n", test_chanbuf.RefCount);
todo_wine ok(!stubMessage.pRpcChannelBuffer, "dangling pRpcChannelBuffer = %p\n", stubMessage.pRpcChannelBuffer);
ok(!stubMessage.pRpcChannelBuffer, "dangling pRpcChannelBuffer = %p\n", stubMessage.pRpcChannelBuffer);
}
START_TEST( cstub )