From 65d59d3b3c2f630f2ea862687ecf5f95f8115244 Mon Sep 17 00:00:00 2001
From: Armin Novak <armin.novak@thincast.com>
Date: Sun, 15 Feb 2026 09:15:20 +0100
Subject: [PATCH] [utils,smartcard] check stream length on padding

When reading optional padding in smartcard channel check if padding is
actually there.
---
 libfreerdp/utils/smartcard_operations.c |  3 ++-
 libfreerdp/utils/smartcard_pack.c       | 32 ++++++++++++++-----------
 2 files changed, 20 insertions(+), 15 deletions(-)

Index: freerdp-2.11.7/channels/smartcard/client/smartcard_operations.c
===================================================================
--- freerdp-2.11.7.orig/channels/smartcard/client/smartcard_operations.c
+++ freerdp-2.11.7/channels/smartcard/client/smartcard_operations.c
@@ -2388,8 +2388,8 @@ LONG smartcard_irp_device_control_decode
 	    (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
 	{
 		offset = (RDPDR_DEVICE_IO_REQUEST_LENGTH + RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH);
-		smartcard_unpack_read_size_align(smartcard, irp->input,
-		                                 Stream_GetPosition(irp->input) - offset, 8);
+		if (smartcard_unpack_read_size_align(smartcard, irp->input, Stream_GetPosition(irp->input) - offset, 8) < 0)
+            return STATUS_INVALID_PARAMETER;
 	}
 
 	if (Stream_GetPosition(irp->input) < Stream_Length(irp->input))
Index: freerdp-2.11.7/channels/smartcard/client/smartcard_pack.c
===================================================================
--- freerdp-2.11.7.orig/channels/smartcard/client/smartcard_pack.c
+++ freerdp-2.11.7/channels/smartcard/client/smartcard_pack.c
@@ -185,6 +185,11 @@ static LONG smartcard_ndr_read_ex(wStrea
 		return SCARD_E_NO_MEMORY;
 	Stream_Read(s, r, len);
     const LONG pad = smartcard_unpack_read_size_align(NULL, s, len, 4);
+	if (pad < 0)
+	{
+		free(r);
+		return STATUS_INVALID_PARAMETER;
+	}
 	len += (size_t)pad;
 	*data = r;
     if (plen)
@@ -1671,14 +1676,15 @@ void smartcard_pack_private_type_header(
 LONG smartcard_unpack_read_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, size_t size,
                                       UINT32 alignment)
 {
-	size_t pad;
 	WINPR_UNUSED(smartcard);
-	pad = size;
-	size = (size + alignment - 1) & ~(alignment - 1);
-	pad = size - pad;
+	const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
+	const size_t pad = padsize - size;
 
-	if (pad)
-		Stream_Seek(s, pad);
+	if (pad > 0)
+	{
+		if (!Stream_SafeSeek(s, pad))
+			return -1;
+	}
 
 	return (LONG)pad;
 }
@@ -1686,11 +1692,9 @@ LONG smartcard_unpack_read_size_align(SM
 LONG smartcard_pack_write_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, size_t size,
                                      UINT32 alignment)
 {
-	size_t pad;
 	WINPR_UNUSED(smartcard);
-	pad = size;
-	size = (size + alignment - 1) & ~(alignment - 1);
-	pad = size - pad;
+	const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
+	const size_t pad = padsize - size;
 
 	if (pad)
 	{
@@ -3030,7 +3034,8 @@ LONG smartcard_unpack_transmit_call(SMAR
 		call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
 		pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
 		Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
-		smartcard_unpack_read_size_align(smartcard, s, ioSendPci.cbExtraBytes, 4);
+		if (smartcard_unpack_read_size_align(smartcard, s, ioSendPci.cbExtraBytes, 4) < 0)
+			return STATUS_INVALID_PARAMETER;
 	}
 	else
 	{
@@ -3130,7 +3135,8 @@ LONG smartcard_unpack_transmit_call(SMAR
 			    (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
 			pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
 			Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
-			smartcard_unpack_read_size_align(smartcard, s, ioRecvPci.cbExtraBytes, 4);
+			if (smartcard_unpack_read_size_align(smartcard, s, ioRecvPci.cbExtraBytes, 4) < 0)
+				return STATUS_INVALID_PARAMETER;
 		}
 		else
 		{
