From 70c8acdd6766428103eeac6e4886832b2e78c26c Mon Sep 17 00:00:00 2001 From: Norbert Federa Date: Mon, 26 Jan 2015 19:26:38 +0100 Subject: [PATCH] drdynvc: fix segfaults and a compiler warning If we send a negative creation status while processing the DVC create response pdu in drdynvc_process_create_request() we must also close the created channel. Otherwise we will get duplicated channel IDs in the channel manager's array list because the server will eventually reuse the channel ids which we have reported as failed in previous creation responses. In order to protect the client from duplicated IDs sent by buggy or malicious servers I've added an appropriate check in dvcman_channel_new() which will now return NULL in this case. Also added a missing NULL check for the result of dvcman_channel_new() in dvcman_create_channel(). --- channels/drdynvc/client/drdynvc_main.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index a6c5e61ec..086e02069 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -28,7 +28,7 @@ #define TAG CHANNELS_TAG("drdynvc.client") -static void dvcman_channel_free(DVCMAN_CHANNEL* channel); +static void dvcman_channel_free(void* channel); static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag) { @@ -220,6 +220,12 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* pChannelMgr { DVCMAN_CHANNEL* channel; + if (dvcman_find_channel_by_id(pChannelMgr, ChannelId)) + { + WLog_ERR(TAG, "Protocol error: Duplicated ChannelId %d (%s)!", ChannelId, ChannelName); + return NULL; + } + channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL)); if (!channel) @@ -234,8 +240,10 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* pChannelMgr return channel; } -void dvcman_channel_free(DVCMAN_CHANNEL* channel) +void dvcman_channel_free(void* arg) { + DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) arg; + if (channel->channel_callback) { channel->channel_callback->OnClose(channel->channel_callback); @@ -339,6 +347,9 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel channel = dvcman_channel_new(pChannelMgr, ChannelId, ChannelName); + if (!channel) + return 1; + channel->status = 1; ArrayList_Add(dvcman->channels, channel); @@ -748,6 +759,7 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb { WLog_DBG(TAG, "no listener"); Stream_Write_UINT32(data_out, (UINT32)(-1)); + dvcman_close_channel(drdynvc->channel_mgr, ChannelId); } status = drdynvc_send(drdynvc, data_out);