[PATCH v2 4/7] crypt32: Fix filling short output in CertGetNameStringW().

Paul Gofman pgofman at codeweavers.com
Thu Apr 14 12:57:05 CDT 2022


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/crypt32/str.c       | 100 +++++++++++++++------------------------
 dlls/crypt32/tests/str.c |   3 +-
 2 files changed, 39 insertions(+), 64 deletions(-)

diff --git a/dlls/crypt32/str.c b/dlls/crypt32/str.c
index 732dcb5ae33..ad0c71d697f 100644
--- a/dlls/crypt32/str.c
+++ b/dlls/crypt32/str.c
@@ -96,8 +96,8 @@ DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
     return ret;
 }
 
-DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
- LPWSTR psz, DWORD csz)
+static DWORD rdn_value_to_strW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
+                               LPWSTR psz, DWORD csz, BOOL partial_copy)
 {
     DWORD ret = 0, len, i;
 
@@ -117,8 +117,9 @@ DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
     case CERT_RDN_GENERAL_STRING:
         len = pValue->cbData;
         if (!psz || !csz) ret = len;
-        else if (len < csz)
+        else if (len < csz || partial_copy)
         {
+            len = min(len, csz - 1);
             for (i = 0; i < len; ++i)
                 psz[i] = pValue->pbData[i];
             ret = len;
@@ -129,10 +130,11 @@ DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
         len = pValue->cbData / sizeof(WCHAR);
         if (!psz || !csz)
             ret = len;
-        else if (len < csz)
+        else if (len < csz || partial_copy)
         {
             WCHAR *ptr = psz;
 
+            len = min(len, csz - 1);
             for (i = 0; i < len; ++i)
                 ptr[i] = ((LPCWSTR)pValue->pbData)[i];
             ret = len;
@@ -146,6 +148,12 @@ DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
     return ret + 1;
 }
 
+DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
+                                LPWSTR psz, DWORD csz)
+{
+    return rdn_value_to_strW(dwValueType, pValue, psz, csz, FALSE);
+}
+
 static inline BOOL is_quotable_char(WCHAR c)
 {
     switch(c)
@@ -1196,13 +1204,24 @@ static DWORD cert_get_name_from_rdn_attr(DWORD encodingType,
             oid = szOID_RSA_emailAddr;
         nameAttr = CertFindRDNAttr(oid, nameInfo);
         if (nameAttr)
-            ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value,
-             pszNameString, cchNameString);
+            ret = rdn_value_to_strW(nameAttr->dwValueType, &nameAttr->Value,
+             pszNameString, cchNameString, TRUE);
         LocalFree(nameInfo);
     }
     return ret;
 }
 
+static DWORD copy_output_str(WCHAR *dst, const WCHAR *src, DWORD dst_size)
+{
+    DWORD len = wcslen(src);
+
+    if (!dst || !dst_size) return len + 1;
+    len = min(len, dst_size - 1);
+    memcpy(dst, src, len * sizeof(*dst));
+    dst[len] = 0;
+    return len + 1;
+}
+
 DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
  DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString)
 {
@@ -1235,23 +1254,14 @@ DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
         PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
          altNameOID, CERT_ALT_NAME_RFC822_NAME, &info);
 
-        if (entry)
-        {
-            if (!pszNameString)
-                ret = lstrlenW(entry->u.pwszRfc822Name) + 1;
-            else if (cchNameString)
-            {
-                ret = min(lstrlenW(entry->u.pwszRfc822Name), cchNameString - 1);
-                memcpy(pszNameString, entry->u.pwszRfc822Name,
-                 ret * sizeof(WCHAR));
-                pszNameString[ret++] = 0;
-            }
-        }
+        if (entry) ret = copy_output_str(pszNameString, entry->u.pwszRfc822Name, cchNameString);
         if (info)
             LocalFree(info);
         if (!ret)
+        {
             ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType,
              name, szOID_RSA_emailAddr, pszNameString, cchNameString);
+         }
         break;
     }
     case CERT_NAME_RDN_TYPE:
@@ -1308,8 +1318,8 @@ DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
             for (i = 0; !nameAttr && i < ARRAY_SIZE(simpleAttributeOIDs); i++)
                 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], nameInfo);
             if (nameAttr)
-                ret = CertRDNValueToStrW(nameAttr->dwValueType,
-                 &nameAttr->Value, pszNameString, cchNameString);
+                ret = rdn_value_to_strW(nameAttr->dwValueType,
+                 &nameAttr->Value, pszNameString, cchNameString, TRUE);
             LocalFree(nameInfo);
         }
         if (!ret)
@@ -1322,19 +1332,7 @@ DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
             {
                 if (!entry && altInfo->cAltEntry)
                     entry = &altInfo->rgAltEntry[0];
-                if (entry)
-                {
-                    if (!pszNameString)
-                        ret = lstrlenW(entry->u.pwszRfc822Name) + 1;
-                    else if (cchNameString)
-                    {
-                        ret = min(lstrlenW(entry->u.pwszRfc822Name),
-                         cchNameString - 1);
-                        memcpy(pszNameString, entry->u.pwszRfc822Name,
-                         ret * sizeof(WCHAR));
-                        pszNameString[ret++] = 0;
-                    }
-                }
+                if (entry) ret = copy_output_str(pszNameString, entry->u.pwszRfc822Name, cchNameString);
                 LocalFree(altInfo);
             }
         }
@@ -1359,17 +1357,8 @@ DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
         PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
          altNameOID, CERT_ALT_NAME_DNS_NAME, &info);
 
-        if (entry)
-        {
-            if (!pszNameString)
-                ret = lstrlenW(entry->u.pwszDNSName) + 1;
-            else if (cchNameString)
-            {
-                ret = min(lstrlenW(entry->u.pwszDNSName), cchNameString - 1);
-                memcpy(pszNameString, entry->u.pwszDNSName, ret * sizeof(WCHAR));
-                pszNameString[ret++] = 0;
-            }
-        }
+        if (entry) ret = copy_output_str(pszNameString, entry->u.pwszDNSName, cchNameString);
+
         if (info)
             LocalFree(info);
         if (!ret)
@@ -1383,17 +1372,8 @@ DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
         PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext,
          altNameOID, CERT_ALT_NAME_URL, &info);
 
-        if (entry)
-        {
-            if (!pszNameString)
-                ret = lstrlenW(entry->u.pwszURL) + 1;
-            else if (cchNameString)
-            {
-                ret = min(lstrlenW(entry->u.pwszURL), cchNameString - 1);
-                memcpy(pszNameString, entry->u.pwszURL, ret * sizeof(WCHAR));
-                pszNameString[ret++] = 0;
-            }
-        }
+        if (entry) ret = copy_output_str(pszNameString, entry->u.pwszURL, cchNameString);
+
         if (info)
             LocalFree(info);
         break;
@@ -1401,17 +1381,13 @@ DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
     default:
         FIXME("unimplemented for type %ld\n", dwType);
         ret = 0;
+        break;
     }
 done:
     if (!ret)
     {
-        if (!pszNameString)
-            ret = 1;
-        else if (cchNameString)
-        {
-            pszNameString[0] = 0;
-            ret = 1;
-        }
+        ret = 1;
+        if (pszNameString && cchNameString) pszNameString[0] = 0;
     }
     return ret;
 }
diff --git a/dlls/crypt32/tests/str.c b/dlls/crypt32/tests/str.c
index 80467943180..ad2b5b81a9b 100644
--- a/dlls/crypt32/tests/str.c
+++ b/dlls/crypt32/tests/str.c
@@ -773,8 +773,7 @@ static void test_CertGetNameString_value_(unsigned int line, PCCERT_CONTEXT cont
     ok(!wcscmp(strW, expectedW), "line %u: unexpected value %s.\n", line, debugstr_w(strW));
     strW[0] = strW[1] = 0xcccc;
     retlen = CertGetNameStringW(context, type, 0, type_para, strW, len - 1);
-    todo_wine_if(type != CERT_NAME_RDN_TYPE)
-        ok(retlen == len - 1, "line %u: unexpected len %lu, expected %lu.\n", line, retlen, len - 1);
+    ok(retlen == len - 1, "line %u: unexpected len %lu, expected %lu.\n", line, retlen, len - 1);
     ok(!wcsncmp(strW, expectedW, retlen - 1), "line %u: string data mismatch.\n", line);
     ok(!strW[retlen - 1], "line %u: string is not zero terminated.\n", line);
     retlen = CertGetNameStringA(context, type, 0, type_para, NULL, len - 1);
-- 
2.35.1




More information about the wine-devel mailing list