freerdp/channels-cliprdr-validate-capabilitySetLength-in-server-caps.patch
2026-07-21 07:46:43 -04:00

74 lines
2.8 KiB
Diff

From ff87e97d62f699826f6b8fc8f754e979d2c87ecb Mon Sep 17 00:00:00 2001
From: Kevin Valerio <kvalerio@protonmail.com>
Date: Wed, 29 Apr 2026 22:39:54 +0200
Subject: [PATCH] fix(cliprdr): validate capabilitySetLength in server caps
---
channels/cliprdr/server/cliprdr_main.c | 38 +++++++++++++++++++++++---
1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c
index 3cfa057e3..1aef5b373 100644
--- a/channels/cliprdr/server/cliprdr_main.c
+++ b/channels/cliprdr/server/cliprdr_main.c
@@ -528,15 +528,45 @@ static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, w
for (size_t index = 0; index < capabilities.cCapabilitiesSets; index++)
{
void* tmp = NULL;
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
+ const size_t cap_set_offset = cap_sets_size;
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(CLIPRDR_CAPABILITY_SET)))
goto out;
Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */
Stream_Read_UINT16(s, capabilitySetLength); /* capabilitySetLength (2 bytes) */
+ if (capabilitySetLength < sizeof(CLIPRDR_CAPABILITY_SET))
+ {
+ WLog_ERR(TAG,
+ "invalid capabilitySetLength %" PRIu16 " < %" PRIuz
+ " (capabilitySetType=%" PRIu16 ")",
+ capabilitySetLength, sizeof(CLIPRDR_CAPABILITY_SET), capabilitySetType);
+ goto out;
+ }
+
+ if (!Stream_CheckAndLogRequiredLength(
+ TAG, s, (size_t)capabilitySetLength - sizeof(CLIPRDR_CAPABILITY_SET)))
+ goto out;
+
+ switch (capabilitySetType)
+ {
+ case CB_CAPSTYPE_GENERAL:
+ if (capabilitySetLength != sizeof(CLIPRDR_GENERAL_CAPABILITY_SET))
+ {
+ WLog_ERR(TAG,
+ "invalid capabilitySetLength %" PRIu16 " != %" PRIuz
+ " (capabilitySetType=CB_CAPSTYPE_GENERAL)",
+ capabilitySetLength, sizeof(CLIPRDR_GENERAL_CAPABILITY_SET));
+ goto out;
+ }
+ break;
+ default:
+ WLog_ERR(TAG, "unknown cliprdr capability set: %" PRIu16 "", capabilitySetType);
+ goto out;
+ }
+
cap_sets_size += capabilitySetLength;
- if (cap_sets_size > 0)
- tmp = realloc(capabilities.capabilitySets, cap_sets_size);
+ tmp = realloc(capabilities.capabilitySets, cap_sets_size);
if (tmp == NULL)
{
WLog_ERR(TAG, "capabilities.capabilitySets realloc failed!");
@@ -546,7 +576,7 @@ static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, w
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*)tmp;
- capSet = &(capabilities.capabilitySets[index]);
+ capSet = (CLIPRDR_CAPABILITY_SET*)(((BYTE*)capabilities.capabilitySets) + cap_set_offset);
capSet->capabilitySetType = capabilitySetType;
capSet->capabilitySetLength = capabilitySetLength;
--
2.52.0