crypt32: Fix memory leaks when encoding fails.

This commit is contained in:
Juan Lang 2011-01-18 19:17:46 -08:00 committed by Alexandre Julliard
parent 9745108096
commit 687e29b912
1 changed files with 167 additions and 97 deletions

View File

@ -127,6 +127,14 @@ BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara
return ret;
}
static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
{
if (pEncodePara && pEncodePara->pfnFree)
pEncodePara->pfnFree(pv);
else
LocalFree(pv);
}
BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
{
DWORD bytesNeeded, significantBytes = 0;
@ -201,21 +209,26 @@ BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCE;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCE;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < cItem; i++)
{
ret = items[i].encodeFunc(dwCertEncodingType, NULL,
items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
NULL, pbEncoded, &items[i].size);
NULL, out, &items[i].size);
/* Some functions propagate their errors through the size */
if (!ret)
*pcbEncoded = items[i].size;
pbEncoded += items[i].size;
out += items[i].size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -243,18 +256,23 @@ BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
CRYPT_EncodeLen(len, pbEncoded, &dataLen);
pbEncoded += dataLen;
out = pbEncoded;
*out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
CRYPT_EncodeLen(len, out, &dataLen);
out += dataLen;
ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
pbEncoded, &len);
out, &len);
if (!ret)
{
/* Some functions propagate their errors through the size */
*pcbEncoded = len;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -607,20 +625,24 @@ static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; i < info->cCRLEntry; i++)
{
DWORD size = dataLen;
ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded,
&size);
pbEncoded += size;
ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size);
out += size;
dataLen -= size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -764,20 +786,25 @@ static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; i < exts->cExtension; i++)
{
DWORD size = dataLen;
ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
pbEncoded, &size);
pbEncoded += size;
out, &size);
out += size;
dataLen -= size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -1399,26 +1426,30 @@ static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < info->cRDN; i++)
{
size = bytesNeeded;
ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
&info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
pbEncoded, &size);
out, &size);
if (ret)
{
pbEncoded += size;
out += size;
bytesNeeded -= size;
}
else
*pcbEncoded = size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -1532,20 +1563,25 @@ static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < entries->cEntry; i++)
{
DWORD size = dataLen;
ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
pbEncoded, &size);
pbEncoded += size;
out, &size);
out += size;
dataLen -= size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -1682,21 +1718,26 @@ static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; i < capabilities->cCapability; i++)
{
DWORD size = dataLen;
ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
NULL, &capabilities->rgCapability[i], 0, NULL,
pbEncoded, &size);
pbEncoded += size;
out, &size);
out += size;
dataLen -= size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -1737,20 +1778,25 @@ static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCE;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCE;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; i < noticeRef->cNoticeNumbers; i++)
{
DWORD size = dataLen;
ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
&noticeRef->rgNoticeNumbers[i], 0, NULL, pbEncoded, &size);
pbEncoded += size;
&noticeRef->rgNoticeNumbers[i], 0, NULL, out, &size);
out += size;
dataLen -= size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -1972,14 +2018,6 @@ static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
return ret;
}
static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
{
if (pEncodePara && pEncodePara->pfnFree)
pEncodePara->pfnFree(pv);
else
LocalFree(pv);
}
static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
@ -2271,24 +2309,27 @@ static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < info->cRDN; i++)
{
size = bytesNeeded;
ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
&info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
&size);
&info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
if (ret)
{
pbEncoded += size;
out += size;
bytesNeeded -= size;
}
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -2540,23 +2581,28 @@ static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < info->cAltEntry; i++)
{
DWORD len = dataLen;
ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
if (ret)
{
pbEncoded += len;
out += len;
dataLen -= len;
}
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -2674,20 +2720,25 @@ static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; i < info->cAccDescr; i++)
{
DWORD size = dataLen;
ret = CRYPT_AsnEncodeAccessDescription(
&info->rgAccDescr[i], pbEncoded, &size);
pbEncoded += size;
&info->rgAccDescr[i], out, &size);
out += size;
dataLen -= size;
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -2819,12 +2870,14 @@ static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < info->cPolicyQualifier; i++)
{
items[0].pvStructInfo =
@ -2834,14 +2887,15 @@ static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
size = bytesNeeded;
ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
sizeof(items) / sizeof(items[0]),
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
&size);
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
if (ret)
{
pbEncoded += size;
out += size;
bytesNeeded -= size;
}
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -2900,24 +2954,28 @@ static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < info->cPolicyInfo; i++)
{
size = bytesNeeded;
ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
&info->rgPolicyInfo[i],
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pbEncoded, &size);
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
if (ret)
{
pbEncoded += size;
out += size;
bytesNeeded -= size;
}
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -2979,24 +3037,28 @@ static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < info->cPolicyMapping; i++)
{
size = bytesNeeded;
ret = CRYPT_AsnEncodeCertPolicyMapping(
dwCertEncodingType, &info->rgPolicyMapping[i],
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pbEncoded, &size);
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
if (ret)
{
pbEncoded += size;
out += size;
bytesNeeded -= size;
}
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -3729,23 +3791,28 @@ static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < info->cDistPoint; i++)
{
DWORD len = dataLen;
ret = CRYPT_AsnEncodeDistPoint(
&info->rgDistPoint[i], pbEncoded, &len);
&info->rgDistPoint[i], out, &len);
if (ret)
{
pbEncoded += len;
out += len;
dataLen -= len;
}
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}
@ -3791,25 +3858,28 @@ static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
BYTE *out;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
out = pbEncoded;
*out++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
out += lenBytes;
for (i = 0; ret && i < usage->cUsageIdentifier; i++)
{
size = bytesNeeded;
ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
usage->rgpszUsageIdentifier[i],
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
&size);
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
if (ret)
{
pbEncoded += size;
out += size;
bytesNeeded -= size;
}
}
if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
CRYPT_FreeSpace(pEncodePara, pbEncoded);
}
}
}