[resend PATCH 1/3] crypt32: Fix NULL output buffer handling for CryptBinaryToString().

Nikolay Sivov nsivov at codeweavers.com
Wed Sep 26 05:09:52 CDT 2018


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/crypt32/base64.c       |  98 +++++++++++++++++--------------
 dlls/crypt32/tests/base64.c | 111 ++++++++++++++++++++++++++----------
 2 files changed, 136 insertions(+), 73 deletions(-)

diff --git a/dlls/crypt32/base64.c b/dlls/crypt32/base64.c
index bc30779098..e25e4c10ff 100644
--- a/dlls/crypt32/base64.c
+++ b/dlls/crypt32/base64.c
@@ -215,36 +215,41 @@ static BOOL BinaryToBase64A(const BYTE *pbBinary,
         charsNeeded += strlen(header) + strlen(sep);
     if (trailer)
         charsNeeded += strlen(trailer) + strlen(sep);
-    if (charsNeeded <= *pcchString)
-    {
-        LPSTR ptr = pszString;
-        DWORD size = charsNeeded;
 
-        if (header)
+    if (pszString)
+    {
+        if (charsNeeded <= *pcchString)
         {
-            strcpy(ptr, header);
-            ptr += strlen(ptr);
-            strcpy(ptr, sep);
-            ptr += strlen(sep);
+            LPSTR ptr = pszString;
+            DWORD size = charsNeeded;
+
+            if (header)
+            {
+                strcpy(ptr, header);
+                ptr += strlen(ptr);
+                strcpy(ptr, sep);
+                ptr += strlen(sep);
+            }
+            encodeBase64A(pbBinary, cbBinary, sep, ptr, &size);
+            ptr += size - 1;
+            if (trailer)
+            {
+                strcpy(ptr, trailer);
+                ptr += strlen(ptr);
+               strcpy(ptr, sep);
+            }
+            *pcchString = charsNeeded - 1;
         }
-        encodeBase64A(pbBinary, cbBinary, sep, ptr, &size);
-        ptr += size - 1;
-        if (trailer)
+        else
         {
-            strcpy(ptr, trailer);
-            ptr += strlen(ptr);
-            strcpy(ptr, sep);
+            *pcchString = charsNeeded;
+            SetLastError(ERROR_INSUFFICIENT_BUFFER);
+            ret = FALSE;
         }
-        *pcchString = charsNeeded - 1;
-    }
-    else if (pszString)
-    {
-        *pcchString = charsNeeded;
-        SetLastError(ERROR_INSUFFICIENT_BUFFER);
-        ret = FALSE;
     }
     else
         *pcchString = charsNeeded;
+
     return ret;
 }
 
@@ -409,36 +414,41 @@ static BOOL BinaryToBase64W(const BYTE *pbBinary,
         charsNeeded += strlenW(header) + strlenW(sep);
     if (trailer)
         charsNeeded += strlenW(trailer) + strlenW(sep);
-    if (charsNeeded <= *pcchString)
-    {
-        LPWSTR ptr = pszString;
-        DWORD size = charsNeeded;
 
-        if (header)
+    if (pszString)
+    {
+        if (charsNeeded <= *pcchString)
         {
-            strcpyW(ptr, header);
-            ptr += strlenW(ptr);
-            strcpyW(ptr, sep);
-            ptr += strlenW(sep);
+            LPWSTR ptr = pszString;
+            DWORD size = charsNeeded;
+
+            if (header)
+            {
+                strcpyW(ptr, header);
+                ptr += strlenW(ptr);
+                strcpyW(ptr, sep);
+                ptr += strlenW(sep);
+            }
+            encodeBase64W(pbBinary, cbBinary, sep, ptr, &size);
+            ptr += size - 1;
+            if (trailer)
+            {
+                strcpyW(ptr, trailer);
+                ptr += strlenW(ptr);
+                strcpyW(ptr, sep);
+            }
+            *pcchString = charsNeeded - 1;
         }
-        encodeBase64W(pbBinary, cbBinary, sep, ptr, &size);
-        ptr += size - 1;
-        if (trailer)
+        else
         {
-            strcpyW(ptr, trailer);
-            ptr += strlenW(ptr);
-            strcpyW(ptr, sep);
+            *pcchString = charsNeeded;
+            SetLastError(ERROR_INSUFFICIENT_BUFFER);
+            ret = FALSE;
         }
-        *pcchString = charsNeeded - 1;
-    }
-    else if (pszString)
-    {
-        *pcchString = charsNeeded;
-        SetLastError(ERROR_INSUFFICIENT_BUFFER);
-        ret = FALSE;
     }
     else
         *pcchString = charsNeeded;
+
     return ret;
 }
 
diff --git a/dlls/crypt32/tests/base64.c b/dlls/crypt32/tests/base64.c
index 7bc1ec7d0e..2249e1bf5a 100644
--- a/dlls/crypt32/tests/base64.c
+++ b/dlls/crypt32/tests/base64.c
@@ -96,60 +96,113 @@ static WCHAR *strdupAtoW(const char *str)
 static void encodeAndCompareBase64_A(const BYTE *toEncode, DWORD toEncodeLen,
  DWORD format, const char *expected, const char *header, const char *trailer)
 {
-    DWORD strLen = 0;
+    DWORD strLen, strLen2;
+    const char *ptr;
     LPSTR str = NULL;
     BOOL ret;
 
+    strLen = 0;
     ret = CryptBinaryToStringA(toEncode, toEncodeLen, format, NULL, &strLen);
     ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
-    str = HeapAlloc(GetProcessHeap(), 0, strLen);
-    if (str)
-    {
-        DWORD strLen2 = strLen;
-        LPCSTR ptr = str;
+    ok(strLen > 0, "Unexpected required length.\n");
 
-        ret = CryptBinaryToStringA(toEncode, toEncodeLen, format, str,
-         &strLen2);
-        ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
-        ok(strLen2 == strLen - 1, "Expected length %d, got %d\n",
-         strLen - 1, strLen);
-        if (header)
-        {
-            ok(!strncmp(header, ptr, strlen(header)),
-             "Expected header %s, got %s\n", header, ptr);
-            ptr += strlen(header);
-        }
-        ok(!strncmp(expected, ptr, strlen(expected)),
-         "Expected %s, got %s\n", expected, ptr);
-        ptr += strlen(expected);
-        if (trailer)
-            ok(!strncmp(trailer, ptr, strlen(trailer)),
-             "Expected trailer %s, got %s\n", trailer, ptr);
-        HeapFree(GetProcessHeap(), 0, str);
+    strLen2 = strLen;
+    ret = CryptBinaryToStringA(toEncode, toEncodeLen, format, NULL, &strLen2);
+    ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
+    ok(strLen == strLen2, "Unexpected required length.\n");
+
+    strLen2 = strLen - 1;
+    ret = CryptBinaryToStringA(toEncode, toEncodeLen, format, NULL, &strLen2);
+    ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
+    ok(strLen == strLen2, "Unexpected required length.\n");
+
+    str = heap_alloc(strLen);
+
+    /* Partially filled output buffer. */
+    strLen2 = strLen - 1;
+    str[0] = 0x12;
+    ret = CryptBinaryToStringA(toEncode, toEncodeLen, format, str, &strLen2);
+todo_wine
+    ok((!ret && GetLastError() == ERROR_MORE_DATA) || broken(ret) /* XP */, "CryptBinaryToStringA failed %d, error %d.\n",
+        ret, GetLastError());
+    ok(strLen2 == strLen || broken(strLen2 == strLen - 1), "Expected length %d, got %d\n", strLen - 1, strLen);
+todo_wine {
+    if (header)
+        ok(str[0] == header[0], "Unexpected buffer contents %#x.\n", str[0]);
+    else
+        ok(str[0] == expected[0], "Unexpected buffer contents %#x.\n", str[0]);
+}
+    strLen2 = strLen;
+    ret = CryptBinaryToStringA(toEncode, toEncodeLen, format, str, &strLen2);
+    ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
+    ok(strLen2 == strLen - 1, "Expected length %d, got %d\n", strLen - 1, strLen);
+
+    ptr = str;
+    if (header)
+    {
+        ok(!strncmp(header, ptr, strlen(header)), "Expected header %s, got %s\n", header, ptr);
+        ptr += strlen(header);
     }
+    ok(!strncmp(expected, ptr, strlen(expected)), "Expected %s, got %s\n", expected, ptr);
+    ptr += strlen(expected);
+    if (trailer)
+        ok(!strncmp(trailer, ptr, strlen(trailer)), "Expected trailer %s, got %s\n", trailer, ptr);
+
+    heap_free(str);
 }
 
 static void encode_compare_base64_W(const BYTE *toEncode, DWORD toEncodeLen, DWORD format,
         const WCHAR *expected, const char *header, const char *trailer)
 {
     WCHAR *headerW, *trailerW;
-    DWORD strLen = 0, strLen2;
+    DWORD strLen, strLen2;
+    WCHAR *strW = NULL;
     const WCHAR *ptr;
-    WCHAR *strW;
     BOOL ret;
 
+    strLen = 0;
     ret = CryptBinaryToStringW(toEncode, toEncodeLen, format, NULL, &strLen);
     ok(ret, "CryptBinaryToStringW failed: %d\n", GetLastError());
+    ok(strLen > 0, "Unexpected required length.\n");
 
+    /* Same call with non-zero length value. */
     strLen2 = strLen;
-    strW = heap_alloc(strLen * sizeof(WCHAR));
-    ret = CryptBinaryToStringW(toEncode, toEncodeLen, format, strW, &strLen2);
+    ret = CryptBinaryToStringW(toEncode, toEncodeLen, format, NULL, &strLen2);
     ok(ret, "CryptBinaryToStringW failed: %d\n", GetLastError());
-    ok(strLen2 == strLen - 1, "Expected length %d, got %d\n", strLen - 1, strLen);
+    ok(strLen == strLen2, "Unexpected required length.\n");
+
+    strLen2 = strLen - 1;
+    ret = CryptBinaryToStringW(toEncode, toEncodeLen, format, NULL, &strLen2);
+    ok(ret, "CryptBinaryToStringW failed: %d\n", GetLastError());
+    ok(strLen == strLen2, "Unexpected required length.\n");
+
+    strLen2 = strLen - 1;
+    ret = CryptBinaryToStringW(toEncode, toEncodeLen, format, NULL, &strLen2);
+    ok(ret, "CryptBinaryToStringW failed: %d\n", GetLastError());
+    ok(strLen == strLen2, "Unexpected required length.\n");
+
+    strW = heap_alloc(strLen * sizeof(WCHAR));
 
     headerW = strdupAtoW(header);
     trailerW = strdupAtoW(trailer);
 
+    strLen2 = strLen - 1;
+    strW[0] = 0x1234;
+    ret = CryptBinaryToStringW(toEncode, toEncodeLen, format, strW, &strLen2);
+todo_wine
+    ok((!ret && GetLastError() == ERROR_MORE_DATA) || broken(ret) /* XP */, "CryptBinaryToStringW failed, %d, error %d\n",
+        ret, GetLastError());
+    if (headerW)
+        ok(strW[0] == 0x1234, "Unexpected buffer contents %#x.\n", strW[0]);
+    else
+        ok(strW[0] == 0x1234 || broken(strW[0] != 0x1234) /* XP */, "Unexpected buffer contents %#x.\n", strW[0]);
+
+    strLen2 = strLen;
+    ret = CryptBinaryToStringW(toEncode, toEncodeLen, format, strW, &strLen2);
+    ok(ret, "CryptBinaryToStringW failed: %d\n", GetLastError());
+
+    ok(strLen2 == strLen - 1, "Expected length %d, got %d\n", strLen - 1, strLen);
+
     ptr = strW;
     if (headerW)
     {
-- 
2.19.0




More information about the wine-devel mailing list