[PATCH v2 1/5] crypt32: Test CryptStringToBinary with weird Base64.

Lauri Kenttä lauri.kentta at gmail.com
Tue Feb 14 08:59:32 CST 2017


CryptStringToBinary handles many kinds of weird Base64 strings.
This patch adds tests for those. The tests also show that the exact
header is not important (e.g. X509 CRL accepts any "BEGIN foo").
In addition, there's a test where buffer length is too small, and
this test currently fails on Wine.

v2: Fix buffer overflow and use 0xdeadbeef as last error.
Signed-off-by: Lauri Kenttä <lauri.kentta at gmail.com>
---
 dlls/crypt32/tests/base64.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 104 insertions(+)

diff --git a/dlls/crypt32/tests/base64.c b/dlls/crypt32/tests/base64.c
index 48494b5b25..24e77e2960 100644
--- a/dlls/crypt32/tests/base64.c
+++ b/dlls/crypt32/tests/base64.c
@@ -299,6 +299,44 @@ static void decodeAndCompareBase64_A(LPCSTR toDecode, LPCSTR header,
     }
 }
 
+static void decodeBase64WithLenFmt(LPCSTR str, int len, DWORD fmt, LPCSTR expected, int le, BOOL isBroken)
+{
+    BYTE buf[8] = {0};
+    DWORD bufLen = sizeof(buf)-1, fmtUsed;
+    BOOL ret;
+    SetLastError(0xdeadbeef);
+    ret = pCryptStringToBinaryA(str, len, fmt, buf, &bufLen, NULL, &fmtUsed);
+    buf[bufLen] = 0;
+    if (expected) {
+        BOOL correct = ret && strcmp(expected, (char*)buf) == 0;
+        ok(correct || (isBroken && broken(!ret)),
+         "base64 \"%s\" len %d: expected \"%s\", got \"%s\" (ret %d, le %d)\n",
+         str, len, expected, (char*)buf, ret, GetLastError());
+        if (correct)
+            ok(fmtUsed == fmt, "base64 \"%s\" len %d: expected fmt %d, used %d\n",
+             str, len, fmt, fmtUsed);
+    } else {
+        ok(!ret && GetLastError() == le,
+         "base64 \"%s\" len %d: expected failure, got \"%s\" (ret %d, le %d)\n",
+         str, len, (char*)buf, ret, GetLastError());
+    }
+}
+
+static void decodeBase64WithLenBroken(LPCSTR str, int len, LPCSTR expected, int le)
+{
+    decodeBase64WithLenFmt(str, len, CRYPT_STRING_BASE64, expected, le, TRUE);
+}
+
+static void decodeBase64WithLen(LPCSTR str, int len, LPCSTR expected, int le)
+{
+    decodeBase64WithLenFmt(str, len, CRYPT_STRING_BASE64, expected, le, FALSE);
+}
+
+static void decodeBase64WithFmt(LPCSTR str, DWORD fmt, LPCSTR expected, int le)
+{
+    decodeBase64WithLenFmt(str, 0, fmt, expected, le, FALSE);
+}
+
 struct BadString
 {
     const char *str;
@@ -313,6 +351,7 @@ static void testStringToBinaryA(void)
 {
     BOOL ret;
     DWORD bufLen = 0, i;
+    BYTE buf[8];
 
     ret = pCryptStringToBinaryA(NULL, 0, 0, NULL, NULL, NULL, NULL);
     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
@@ -339,6 +378,71 @@ static void testStringToBinaryA(void)
         ok(!ret && GetLastError() == ERROR_INVALID_DATA,
            "%d: Expected ERROR_INVALID_DATA, got ret=%d le=%u\n", i, ret, GetLastError());
     }
+    /* Weird base64 strings (invalid padding, extra white-space etc.) */
+    decodeBase64WithLen("V=", 0, 0, ERROR_INVALID_DATA);
+    decodeBase64WithLen("VV=", 0, 0, ERROR_INVALID_DATA);
+    decodeBase64WithLen("V==", 0, 0, ERROR_INVALID_DATA);
+    decodeBase64WithLen("V=", 2, 0, ERROR_INVALID_DATA);
+    decodeBase64WithLen("VV=", 3, 0, ERROR_INVALID_DATA);
+    decodeBase64WithLen("V==", 3, 0, ERROR_INVALID_DATA);
+    todo_wine {
+    decodeBase64WithLenBroken("V", 0, "T", 0);
+    decodeBase64WithLenBroken("VV", 0, "U", 0);
+    decodeBase64WithLenBroken("VVV", 0, "UU", 0);
+    decodeBase64WithLen("V", 1, "T", 0);
+    decodeBase64WithLen("VV", 2, "U", 0);
+    decodeBase64WithLen("VVV", 3, "UU", 0);
+    decodeBase64WithLen("V===", 0, "T", 0);
+    decodeBase64WithLen("V========", 0, "T", 0);
+    decodeBase64WithLen("V===", 4, "T", 0);
+    decodeBase64WithLen("V\nVVV", 0, "UUU", 0);
+    decodeBase64WithLen("VV\nVV", 0, "UUU", 0);
+    decodeBase64WithLen("VVV\nV", 0, "UUU", 0);
+    decodeBase64WithLen("V\nVVV", 5, "UUU", 0);
+    decodeBase64WithLen("VV\nVV", 5, "UUU", 0);
+    decodeBase64WithLen("VVV\nV", 5, "UUU", 0);
+    decodeBase64WithLen("VV    VV", 0, "UUU", 0);
+    decodeBase64WithLen("V===VVVV", 0, "T", 0);
+    decodeBase64WithLen("VV==VVVV", 0, "U", 0);
+    decodeBase64WithLen("VVV=VVVV", 0, "UU", 0);
+    decodeBase64WithLen("VVVV=VVVV", 0, "UUU", 0);
+    decodeBase64WithLen("V===VVVV", 8, "T", 0);
+    decodeBase64WithLen("VV==VVVV", 8, "U", 0);
+    decodeBase64WithLen("VVV=VVVV", 8, "UU", 0);
+    decodeBase64WithLen("VVVV=VVVV", 8, "UUU", 0);
+    }
+
+    todo_wine {
+    decodeBase64WithFmt("-----BEGIN-----VVVV-----END-----", CRYPT_STRING_BASE64HEADER, 0, ERROR_INVALID_DATA);
+    decodeBase64WithFmt("-----BEGIN-----VVVV-----END -----", CRYPT_STRING_BASE64HEADER, 0, ERROR_INVALID_DATA);
+    decodeBase64WithFmt("-----BEGIN -----VVVV-----END-----", CRYPT_STRING_BASE64HEADER, 0, ERROR_INVALID_DATA);
+    }
+    decodeBase64WithFmt("-----BEGIN -----VVVV-----END -----", CRYPT_STRING_BASE64HEADER, "UUU", 0);
+
+    todo_wine {
+    decodeBase64WithFmt("-----BEGIN -----V-----END -----", CRYPT_STRING_BASE64HEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN foo-----V-----END -----", CRYPT_STRING_BASE64HEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN foo-----V-----END foo-----", CRYPT_STRING_BASE64HEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN -----V-----END foo-----", CRYPT_STRING_BASE64HEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN -----V-----END -----", CRYPT_STRING_BASE64X509CRLHEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN foo-----V-----END -----", CRYPT_STRING_BASE64X509CRLHEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN foo-----V-----END foo-----", CRYPT_STRING_BASE64X509CRLHEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN -----V-----END foo-----", CRYPT_STRING_BASE64X509CRLHEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN -----V-----END -----", CRYPT_STRING_BASE64REQUESTHEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN foo-----V-----END -----", CRYPT_STRING_BASE64REQUESTHEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN foo-----V-----END foo-----", CRYPT_STRING_BASE64REQUESTHEADER, "T", 0);
+    decodeBase64WithFmt("-----BEGIN -----V-----END foo-----", CRYPT_STRING_BASE64REQUESTHEADER, "T", 0);
+    }
+
+    /* Too small buffer */
+    buf[0] = 0;
+    bufLen = 4;
+    ret = pCryptStringToBinaryA("VVVVVVVV", 8, CRYPT_STRING_BASE64, (BYTE*)buf, &bufLen, NULL, NULL);
+    todo_wine
+    ok(!ret && bufLen == 4 && buf[0] == 0,
+     "Expected ret 0, bufLen 4, buf[0] '\\0', got ret %d, bufLen %d, buf[0] '%c'\n",
+     ret, bufLen, buf[0]);
+
     /* Good strings */
     for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
     {
-- 
2.11.1




More information about the wine-patches mailing list