Juan Lang : crypt32: Explicitly count bytes to copy in DecodeCopyBytes.

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


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

Author: Juan Lang <juan.lang at gmail.com>
Date:   Mon Sep 17 17:55:13 2007 -0700

crypt32: Explicitly count bytes to copy in DecodeCopyBytes.

---

 dlls/crypt32/decode.c       |  127 ++++++++++++++++++++++++++++++++++---------
 dlls/crypt32/tests/encode.c |    1 -
 2 files changed, 101 insertions(+), 27 deletions(-)

diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c
index 8da7138..0125fef 100644
--- a/dlls/crypt32/decode.c
+++ b/dlls/crypt32/decode.c
@@ -361,10 +361,26 @@ static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
                             }
                             else
                             {
-                                ptr += itemDecoded;
-                                decoded += itemDecoded;
-                                TRACE("item %d: decoded %d bytes\n", i,
-                                 itemDecoded);
+                                if (itemLen == CMSG_INDEFINITE_LENGTH)
+                                {
+                                    if (itemDecoded > itemEncodedLen - 2 ||
+                                     *(ptr + itemDecoded) != 0 ||
+                                     *(ptr + itemDecoded + 1) != 0)
+                                    {
+                                        TRACE("expected 0 TLV\n");
+                                        SetLastError(CRYPT_E_ASN1_CORRUPT);
+                                        ret = FALSE;
+                                    }
+                                    else
+                                        itemDecoded += 2;
+                                }
+                                if (ret)
+                                {
+                                    ptr += itemDecoded;
+                                    decoded += itemDecoded;
+                                    TRACE("item %d: decoded %d bytes\n", i,
+                                     itemDecoded);
+                                }
                             }
                         }
                         else if (items[i].optional &&
@@ -1875,41 +1891,100 @@ static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
     return ret;
 }
 
+static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD *pcbDecoded)
+{
+    BOOL ret = TRUE, done = FALSE;
+    DWORD indefiniteNestingLevels = 0, decoded = 0;
+
+    TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
+
+    do {
+        DWORD dataLen;
+
+        if (!cbEncoded)
+            done = TRUE;
+        else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
+         &dataLen)))
+        {
+            BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+            if (dataLen == CMSG_INDEFINITE_LENGTH)
+            {
+                indefiniteNestingLevels++;
+                pbEncoded += 1 + lenBytes;
+                cbEncoded -= 1 + lenBytes;
+                decoded += 1 + lenBytes;
+                TRACE("indefiniteNestingLevels = %d\n",
+                 indefiniteNestingLevels);
+            }
+            else
+            {
+                if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
+                 indefiniteNestingLevels)
+                {
+                    indefiniteNestingLevels--;
+                    TRACE("indefiniteNestingLevels = %d\n",
+                     indefiniteNestingLevels);
+                }
+                pbEncoded += 1 + lenBytes + dataLen;
+                cbEncoded -= 1 + lenBytes + dataLen;
+                decoded += 1 + lenBytes + dataLen;
+                if (!indefiniteNestingLevels)
+                    done = TRUE;
+            }
+        }
+    } while (ret && !done);
+    /* If we haven't found all 0 TLVs, we haven't found the end */
+    if (ret && indefiniteNestingLevels)
+    {
+        SetLastError(CRYPT_E_ASN1_EOD);
+        ret = FALSE;
+    }
+    if (ret)
+        *pcbDecoded = decoded;
+    TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
+    return ret;
+}
+
 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
  DWORD *pcbDecoded)
 {
     BOOL ret = TRUE;
-    DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
+    DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
 
     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
      pvStructInfo, *pcbStructInfo);
 
-    if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
-        bytesNeeded += cbEncoded;
-    if (pcbDecoded)
-        *pcbDecoded = cbEncoded;
-    if (!pvStructInfo)
-        *pcbStructInfo = bytesNeeded;
-    else if (*pcbStructInfo < bytesNeeded)
-    {
-        SetLastError(ERROR_MORE_DATA);
-        *pcbStructInfo = bytesNeeded;
-        ret = FALSE;
-    }
-    else
+    if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
     {
-        PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
-
-        *pcbStructInfo = bytesNeeded;
-        blob->cbData = cbEncoded;
-        if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
-            blob->pbData = (LPBYTE)pbEncoded;
+        if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
+            bytesNeeded += encodedLen;
+        if (!pvStructInfo)
+            *pcbStructInfo = bytesNeeded;
+        else if (*pcbStructInfo < bytesNeeded)
+        {
+            SetLastError(ERROR_MORE_DATA);
+            *pcbStructInfo = bytesNeeded;
+            ret = FALSE;
+        }
         else
         {
-            assert(blob->pbData);
-            memcpy(blob->pbData, pbEncoded, blob->cbData);
+            PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
+
+            *pcbStructInfo = bytesNeeded;
+            blob->cbData = encodedLen;
+            if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+                blob->pbData = (LPBYTE)pbEncoded;
+            else
+            {
+                assert(blob->pbData);
+                memcpy(blob->pbData, pbEncoded, blob->cbData);
+            }
         }
+        if (pcbDecoded)
+            *pcbDecoded = encodedLen;
     }
     return ret;
 }
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index 3e29db0..eaed27b 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -4891,7 +4891,6 @@ static void test_decodePKCSContentInfo(DWORD dwEncoding)
 
         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
-        todo_wine
         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
          info->Content.cbData);
         LocalFree(buf);




More information about the wine-cvs mailing list