From 070f9e070c59a121cd93541835dc0086084bb6ad Mon Sep 17 00:00:00 2001 From: Ondrej Holy Date: Tue, 17 Feb 2026 11:05:59 +0100 Subject: [PATCH] [utils,smartcard] add length validity checks Backport of commit 57c5647d98c2a026de8b681159cb188ca0439ef8. Co-Authored-By: Cursor --- channels/smartcard/client/smartcard_pack.c | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index f70eb4e5d..687f1110b 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -98,13 +98,16 @@ static BOOL smartcard_ndr_pointer_read_(wStream* s, UINT32* index, UINT32* ptr, return TRUE; } -static LONG smartcard_ndr_read(wStream* s, BYTE** data, size_t min, size_t elementSize, - ndr_ptr_t type) +static LONG smartcard_ndr_read_ex(wStream* s, BYTE** data, size_t min, + size_t elementSize, ndr_ptr_t type, size_t* plen) { size_t len, offset, len2; void* r; size_t required; + if (plen) + *plen = 0; + switch (type) { case NDR_PTR_FULL: @@ -181,11 +184,20 @@ static LONG smartcard_ndr_read(wStream* s, BYTE** data, size_t min, size_t eleme if (!r) return SCARD_E_NO_MEMORY; Stream_Read(s, r, len); - smartcard_unpack_read_size_align(NULL, s, len, 4); + const LONG pad = smartcard_unpack_read_size_align(NULL, s, len, 4); + len += (size_t)pad; *data = r; + if (plen) + *plen = len; return STATUS_SUCCESS; } +static LONG smartcard_ndr_read(wStream* s, BYTE** data, size_t min, size_t elementSize, + ndr_ptr_t type) +{ + return smartcard_ndr_read_ex(s, data, min, elementSize, type, NULL); +} + static BOOL smartcard_ndr_pointer_write(wStream* s, UINT32* index, DWORD length) { const UINT32 ndrPtr = 0x20000 + (*index) * 4; @@ -3427,12 +3439,15 @@ LONG smartcard_unpack_set_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s, S if (ndrPtr) { - // TODO: call->cbAttrLen was larger than the pointer value. - // TODO: Maybe need to refine the checks? - status = smartcard_ndr_read(s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE); + size_t len = 0; + status = smartcard_ndr_read_ex(s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE, &len); if (status != SCARD_S_SUCCESS) return status; + if (call->cbAttrLen > len) + call->cbAttrLen = (DWORD)len; } + else + call->cbAttrLen = 0; smartcard_trace_set_attrib_call(smartcard, call); return SCARD_S_SUCCESS; } -- 2.52.0