[winpr,smartcard] fix returned attribute length

SCARD_ATTR_DEVICE_SYSTEM_NAME_W requires twice the size, so multiply
before return.
This commit is contained in:
Armin Novak
2026-02-11 19:18:40 +01:00
parent fb3f8aa3b6
commit 606250f4cb

View File

@@ -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)
{