diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c index 71610583153..a5229b5b6f5 100644 --- a/dlls/crypt32/decode.c +++ b/dlls/crypt32/decode.c @@ -536,7 +536,7 @@ static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc, { DWORD dataLen; - if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) + if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen))) { DWORD bytesNeeded, cItems = 0, decoded; BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); @@ -549,53 +549,76 @@ static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc, if (dataLen) { const BYTE *ptr; + BOOL doneDecoding = FALSE; - for (ptr = pbEncoded + 1 + lenBytes; ret && - ptr - pbEncoded - 1 - lenBytes < dataLen; ) + for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; ) { - DWORD itemLenBytes, itemDataLen, itemDecoded, size = 0; + DWORD itemLenBytes; itemLenBytes = GET_LEN_BYTES(ptr[1]); - /* Each item decoded may not tolerate extraneous bytes, so - * get the length of the next element and pass it directly. - */ - ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded), - &itemDataLen); - if (ret) - ret = arrayDesc->decodeFunc(ptr, - 1 + itemLenBytes + itemDataLen, - dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size, - &itemDecoded); - if (ret) + if (dataLen == CMSG_INDEFINITE_LENGTH) { - DWORD nextLen; + if (ptr[0] == 0) + { + doneDecoding = TRUE; + if (itemLenBytes != 1 || ptr[1] != 0) + { + SetLastError(CRYPT_E_ASN1_CORRUPT); + ret = FALSE; + } + else + decoded += 2; + } + } + else if (ptr - pbEncoded - 1 - lenBytes >= dataLen) + doneDecoding = TRUE; + if (!doneDecoding) + { + DWORD itemDataLen, itemDecoded, size = 0; - cItems++; - if (itemSizes != &itemSize) - itemSizes = CryptMemRealloc(itemSizes, - cItems * sizeof(struct AsnArrayItemSize)); - else if (cItems > 1) + /* Each item decoded may not tolerate extraneous bytes, + * so get the length of the next element and pass it + * directly. + */ + ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded), + &itemDataLen); + if (ret) + ret = arrayDesc->decodeFunc(ptr, + 1 + itemLenBytes + itemDataLen, + dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size, + &itemDecoded); + if (ret) { - itemSizes = - CryptMemAlloc( - cItems * sizeof(struct AsnArrayItemSize)); + DWORD nextLen; + + cItems++; + if (itemSizes != &itemSize) + itemSizes = CryptMemRealloc(itemSizes, + cItems * sizeof(struct AsnArrayItemSize)); + else if (cItems > 1) + { + itemSizes = + CryptMemAlloc( + cItems * sizeof(struct AsnArrayItemSize)); + if (itemSizes) + memcpy(itemSizes, &itemSize, + sizeof(itemSize)); + } if (itemSizes) - memcpy(itemSizes, &itemSize, sizeof(itemSize)); + { + decoded += itemDecoded; + itemSizes[cItems - 1].encodedLen = + 1 + itemLenBytes + itemDataLen; + itemSizes[cItems - 1].size = size; + bytesNeeded += size; + ret = CRYPT_GetLen(ptr, + cbEncoded - (ptr - pbEncoded), &nextLen); + if (ret) + ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); + } + else + ret = FALSE; } - if (itemSizes) - { - decoded += itemDecoded; - itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes - + itemDataLen; - itemSizes[cItems - 1].size = size; - bytesNeeded += size; - ret = CRYPT_GetLen(ptr, - cbEncoded - (ptr - pbEncoded), &nextLen); - if (ret) - ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]); - } - else - ret = FALSE; } } } diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index 37046b0efd4..13d288b4af9 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -1015,7 +1015,6 @@ static void test_decodeName(DWORD dwEncoding) ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence, sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize); - todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); if (ret) {