From 606250f4cb311025d5c75076ec326c9973584134 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 11 Feb 2026 19:18:40 +0100 Subject: [PATCH] [winpr,smartcard] fix returned attribute length SCARD_ATTR_DEVICE_SYSTEM_NAME_W requires twice the size, so multiply before return. --- winpr/libwinpr/smartcard/smartcard_pcsc.c | 105 ++++++++++++++-------- 1 file changed, 68 insertions(+), 37 deletions(-) diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index 5987f841a..e316e1843 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -2510,53 +2510,86 @@ static LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWORD dwA return status; } -static LONG PCSC_ReadDeviceSystemName(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard, - DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) +static LONG PCSC_ReadDeviceSystemNameGet(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard, + DWORD dwAttrId, LPBYTE* pbAttr, LPDWORD pcbAttrLen) { - /* Get reader name from SCardStatus */ + PCSC_DWORD cchReader = 0; + PCSC_DWORD cbAtr = 0; PCSC_DWORD dwState = 0; PCSC_DWORD dwProtocol = 0; - LONG status = 0; - DWORD cbAttrLen = *pcbAttrLen; - if (cbAttrLen == SCARD_AUTOALLOCATE) - return SCARD_E_UNEXPECTED; + const PCSC_LONG rc = + g_PCSC.pfnSCardStatus(hCard, NULL, &cchReader, &dwState, &dwProtocol, NULL, &cbAtr); + if (rc != SCARD_S_SUCCESS) + return (LONG)rc; - if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W) - cbAttrLen /= sizeof(WCHAR); - - PCSC_DWORD cbAtr = 0; - PCSC_DWORD cchReader = cbAttrLen; - const PCSC_LONG rc = g_PCSC.pfnSCardStatus(hCard, (LPSTR)pbAttr, &cchReader, &dwState, - &dwProtocol, NULL, &cbAtr); - - *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, cchReader); - status = WINPR_ASSERTING_INT_CAST(LONG, rc); - if (status != SCARD_S_SUCCESS) - return status; - - if (cchReader > cbAttrLen) - return SCARD_E_INSUFFICIENT_BUFFER; + void* tmp = calloc(cchReader + 1, sizeof(CHAR)); + if (!tmp) + return SCARD_E_NO_MEMORY; + const PCSC_LONG rc2 = + g_PCSC.pfnSCardStatus(hCard, tmp, &cchReader, &dwState, &dwProtocol, NULL, &cbAtr); + if (rc2 != SCARD_S_SUCCESS) + { + free(tmp); + return (LONG)rc2; + } if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W) { - size_t wlen = 0; - WCHAR* tmp = ConvertMszUtf8NToWCharAlloc((LPSTR)pbAttr, cchReader, &wlen); - if (!tmp) - return SCARD_E_NO_MEMORY; - - /* utf-8 to utf-16 is no simple y=x*2, check again if the size fits. */ - if (wlen > cbAttrLen) + size_t len = 0; + void* data = ConvertMszUtf8NToWCharAlloc(tmp, cchReader, &len); + if (!data) { free(tmp); - return SCARD_E_INSUFFICIENT_BUFFER; + return SCARD_E_NO_MEMORY; } - *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, MIN(wlen, cchReader) * sizeof(WCHAR)); - memcpy(pbAttr, tmp, *pcbAttrLen); + len *= sizeof(WCHAR); + + cchReader = WINPR_ASSERTING_INT_CAST(PCSC_DWORD, len); free(tmp); + tmp = data; } - return status; + *pbAttr = tmp; + *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, cchReader); + return SCARD_S_SUCCESS; +} + +static LONG PCSC_ReadDeviceSystemName(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard, + DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) +{ + BYTE* tmp = NULL; + DWORD cbAttrLen = 0; + const LONG rc = PCSC_ReadDeviceSystemNameGet(hContext, hCard, dwAttrId, &tmp, &cbAttrLen); + if (rc != SCARD_S_SUCCESS) + return rc; + + if (*pcbAttrLen == SCARD_AUTOALLOCATE) + { + if (!PCSC_AddMemoryBlock(hContext, tmp)) + { + free(tmp); + return SCARD_E_NO_MEMORY; + } + + *pcbAttrLen = cbAttrLen; + *(BYTE**)pbAttr = tmp; + return SCARD_S_SUCCESS; + } + + if (pbAttr) + memcpy(pbAttr, tmp, MIN(cbAttrLen, *pcbAttrLen)); + free(tmp); + + if (pbAttr) + { + if (cbAttrLen > *pcbAttrLen) + return SCARD_E_INSUFFICIENT_BUFFER; + } + + *pcbAttrLen = cbAttrLen; + + return SCARD_S_SUCCESS; } static LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, @@ -2695,13 +2728,11 @@ static LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE } else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_A) { - if (!pcbAttrLenAlloc) - status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen); + status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen); } else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W) { - if (!pcbAttrLenAlloc) - status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen); + status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen); } else if (dwAttrId == SCARD_ATTR_DEVICE_UNIT) {