From 81e49eff0fa97293b3f1d1805989c2f5434a2e2e Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Mon, 17 Sep 2007 16:58:25 -0700 Subject: [PATCH] Support indefinite-length encoded arrays --- dlls/crypt32/decode.c | 101 ++++++++++++++++++++++++++----------------- dlls/crypt32/tests/encode.c | 1 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c index 7161058..a5229b5 100644 --- a/dlls/crypt32/decode.c +++ b/dlls/crypt32/decode.c @@ -536,7 +536,7 @@ static BOOL CRYPT_AsnDecodeArray(const s { 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 s 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; - - cItems++; - if (itemSizes != &itemSize) - itemSizes = CryptMemRealloc(itemSizes, - cItems * sizeof(struct AsnArrayItemSize)); - else if (cItems > 1) + if (ptr[0] == 0) { - itemSizes = - CryptMemAlloc( - cItems * sizeof(struct AsnArrayItemSize)); - if (itemSizes) - memcpy(itemSizes, &itemSize, sizeof(itemSize)); + doneDecoding = TRUE; + if (itemLenBytes != 1 || ptr[1] != 0) + { + SetLastError(CRYPT_E_ASN1_CORRUPT); + ret = FALSE; + } + else + decoded += 2; } - if (itemSizes) + } + else if (ptr - pbEncoded - 1 - lenBytes >= dataLen) + doneDecoding = TRUE; + if (!doneDecoding) + { + DWORD itemDataLen, itemDecoded, size = 0; + + /* 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) { - 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]); + 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) + { + 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; } - else - ret = FALSE; } } } diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index 37046b0..13d288b 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -1015,7 +1015,6 @@ static void test_decodeName(DWORD dwEnco 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) { -- 1.4.1