Juan Lang : crypt32: Support indefinite-length encoded arrays.

Alexandre Julliard julliard at winehq.org
Tue Sep 18 05:31:22 CDT 2007


Module: wine
Branch: master
Commit: 5d168bd4c0fe9725114a652175ffcab01a25fb91
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5d168bd4c0fe9725114a652175ffcab01a25fb91

Author: Juan Lang <juan.lang at gmail.com>
Date:   Mon Sep 17 16:58:25 2007 -0700

crypt32: 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 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;
-
-                        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 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)
     {




More information about the wine-cvs mailing list