Merge pull request #4871 from akallabeth/drdynvc_checks
Fix for #4866: Added additional length checks
This commit is contained in:
commit
205c612820
@ -639,8 +639,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc,
|
|||||||
if (channel->dvc_data)
|
if (channel->dvc_data)
|
||||||
{
|
{
|
||||||
/* Fragmented data */
|
/* Fragmented data */
|
||||||
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(
|
if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data))
|
||||||
channel->dvc_data))
|
|
||||||
{
|
{
|
||||||
WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!");
|
WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!");
|
||||||
Stream_Release(channel->dvc_data);
|
Stream_Release(channel->dvc_data);
|
||||||
@ -648,7 +647,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc,
|
|||||||
return ERROR_INVALID_DATA;
|
return ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize);
|
Stream_Copy(data, channel->dvc_data, dataSize);
|
||||||
|
|
||||||
if (Stream_GetPosition(channel->dvc_data) >= channel->dvc_data_length)
|
if (Stream_GetPosition(channel->dvc_data) >= channel->dvc_data_length)
|
||||||
{
|
{
|
||||||
@ -880,6 +879,9 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
if (!drdynvc)
|
if (!drdynvc)
|
||||||
return CHANNEL_RC_BAD_INIT_HANDLE;
|
return CHANNEL_RC_BAD_INIT_HANDLE;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 3)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
WLog_Print(drdynvc->log, WLOG_TRACE, "capability_request Sp=%d cbChId=%d", Sp, cbChId);
|
WLog_Print(drdynvc->log, WLOG_TRACE, "capability_request Sp=%d cbChId=%d", Sp, cbChId);
|
||||||
Stream_Seek(s, 1); /* pad */
|
Stream_Seek(s, 1); /* pad */
|
||||||
Stream_Read_UINT16(s, drdynvc->version);
|
Stream_Read_UINT16(s, drdynvc->version);
|
||||||
@ -889,6 +891,9 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
*/
|
*/
|
||||||
if ((drdynvc->version == 2) || (drdynvc->version == 3))
|
if ((drdynvc->version == 2) || (drdynvc->version == 3))
|
||||||
{
|
{
|
||||||
|
if (Stream_GetRemainingLength(s) < 8)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
Stream_Read_UINT16(s, drdynvc->PriorityCharge0);
|
Stream_Read_UINT16(s, drdynvc->PriorityCharge0);
|
||||||
Stream_Read_UINT16(s, drdynvc->PriorityCharge1);
|
Stream_Read_UINT16(s, drdynvc->PriorityCharge1);
|
||||||
Stream_Read_UINT16(s, drdynvc->PriorityCharge2);
|
Stream_Read_UINT16(s, drdynvc->PriorityCharge2);
|
||||||
@ -900,6 +905,21 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT32 drdynvc_cblen_to_bytes(int cbLen)
|
||||||
|
{
|
||||||
|
switch (cbLen)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen)
|
static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen)
|
||||||
{
|
{
|
||||||
UINT32 val;
|
UINT32 val;
|
||||||
@ -935,6 +955,8 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
UINT32 ChannelId;
|
UINT32 ChannelId;
|
||||||
wStream* data_out;
|
wStream* data_out;
|
||||||
UINT channel_status;
|
UINT channel_status;
|
||||||
|
char* name;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
if (!drdynvc)
|
if (!drdynvc)
|
||||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
|
||||||
@ -957,13 +979,20 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
drdynvc->state = DRDYNVC_STATE_READY;
|
drdynvc->state = DRDYNVC_STATE_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||||
pos = Stream_GetPosition(s);
|
pos = Stream_GetPosition(s);
|
||||||
|
name = Stream_Pointer(s);
|
||||||
|
length = Stream_GetRemainingLength(s);
|
||||||
|
|
||||||
|
if (strnlen(name, length) >= length)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s",
|
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s",
|
||||||
ChannelId,
|
ChannelId, name);
|
||||||
Stream_Pointer(s));
|
channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name);
|
||||||
channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId,
|
|
||||||
(char*) Stream_Pointer(s));
|
|
||||||
data_out = Stream_New(NULL, pos + 4);
|
data_out = Stream_New(NULL, pos + 4);
|
||||||
|
|
||||||
if (!data_out)
|
if (!data_out)
|
||||||
@ -1024,6 +1053,10 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
UINT status;
|
UINT status;
|
||||||
UINT32 Length;
|
UINT32 Length;
|
||||||
UINT32 ChannelId;
|
UINT32 ChannelId;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId) + drdynvc_cblen_to_bytes(Sp))
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||||
Length = drdynvc_read_variable_uint(s, Sp);
|
Length = drdynvc_read_variable_uint(s, Sp);
|
||||||
WLog_Print(drdynvc->log, WLOG_DEBUG,
|
WLog_Print(drdynvc->log, WLOG_DEBUG,
|
||||||
@ -1047,6 +1080,10 @@ static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId,
|
|||||||
wStream* s)
|
wStream* s)
|
||||||
{
|
{
|
||||||
UINT32 ChannelId;
|
UINT32 ChannelId;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||||
WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp,
|
WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp,
|
||||||
cbChId,
|
cbChId,
|
||||||
@ -1066,6 +1103,10 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
|
|||||||
UINT error;
|
UINT error;
|
||||||
UINT32 ChannelId;
|
UINT32 ChannelId;
|
||||||
wStream* data_out;
|
wStream* data_out;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||||
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"",
|
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"",
|
||||||
Sp,
|
Sp,
|
||||||
@ -1108,6 +1149,10 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s)
|
|||||||
int Cmd;
|
int Cmd;
|
||||||
int Sp;
|
int Sp;
|
||||||
int cbChId;
|
int cbChId;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 1)
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
|
||||||
Stream_Read_UINT8(s, value);
|
Stream_Read_UINT8(s, value);
|
||||||
Cmd = (value & 0xf0) >> 4;
|
Cmd = (value & 0xf0) >> 4;
|
||||||
Sp = (value & 0x0c) >> 2;
|
Sp = (value & 0x0c) >> 2;
|
||||||
@ -1166,7 +1211,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
|
|||||||
return CHANNEL_RC_NO_MEMORY;
|
return CHANNEL_RC_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
|
if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
|
||||||
{
|
{
|
||||||
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
|
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
|
||||||
Stream_Free(drdynvc->data_in, TRUE);
|
Stream_Free(drdynvc->data_in, TRUE);
|
||||||
|
Loading…
Reference in New Issue
Block a user