Andrew Nguyen : dxdiagn: Fix string copy behavior with an excessively short buffer in IDxDiagContainer ::EnumPropNames.

Alexandre Julliard julliard at winehq.org
Mon Mar 15 12:19:41 CDT 2010


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

Author: Andrew Nguyen <arethusa26 at gmail.com>
Date:   Sun Mar 14 16:36:53 2010 -0600

dxdiagn: Fix string copy behavior with an excessively short buffer in IDxDiagContainer::EnumPropNames.

---

 dlls/dxdiagn/container.c       |   10 +++---
 dlls/dxdiagn/tests/container.c |   62 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/dlls/dxdiagn/container.c b/dlls/dxdiagn/container.c
index 3829bb8..0682145 100644
--- a/dlls/dxdiagn/container.c
+++ b/dlls/dxdiagn/container.c
@@ -196,16 +196,16 @@ static HRESULT WINAPI IDxDiagContainerImpl_EnumPropNames(PDXDIAGCONTAINER iface,
 
   p = This->properties;
   while (NULL != p) {
-    if (dwIndex == i) {  
-      if (cchPropName <= strlenW(p->vName)) {
-        return DXDIAG_E_INSUFFICIENT_BUFFER;
-      }
+    if (dwIndex == i) {
+      TRACE("Found property name %s, copying string\n", debugstr_w(p->vName));
       lstrcpynW(pwszPropName, p->vName, cchPropName);
-      return S_OK;
+      return (cchPropName <= strlenW(p->vName)) ?
+              DXDIAG_E_INSUFFICIENT_BUFFER : S_OK;
     }
     p = p->next;
     ++i;
   }
+  TRACE("Failed to find property name at specified index\n");
   return E_INVALIDARG;
 }
 
diff --git a/dlls/dxdiagn/tests/container.c b/dlls/dxdiagn/tests/container.c
index d1541e3..e525709 100644
--- a/dlls/dxdiagn/tests/container.c
+++ b/dlls/dxdiagn/tests/container.c
@@ -394,7 +394,6 @@ static void test_EnumPropNames(void)
     IDxDiagContainer *child = NULL;
     DWORD count, index, propcount;
     static const WCHAR testW[] = {'t','e','s','t',0};
-    static const WCHAR zerotestW[] = {0,'e','s','t',0};
 
     if (!create_root_IDxDiagContainer())
     {
@@ -460,6 +459,67 @@ static void test_EnumPropNames(void)
     ok(!memcmp(property, testW, sizeof(testW)),
        "Expected the property buffer to be unchanged, got %s\n", wine_dbgstr_w(property));
 
+    trace("Starting property enumeration of the %s container:\n", wine_dbgstr_w(container));
+
+    /* We should be able to enumerate as many properties as the value that
+     * IDxDiagContainer::GetNumberOfProps returns. */
+    for (index = 0; index <= propcount; index++)
+    {
+        /* A buffer size of 1 is unlikely to be valid, as only a null terminator
+         * could be stored, and it is unlikely that a property name could be empty. */
+        DWORD buffersize = 1;
+
+        memcpy(property, testW, sizeof(testW));
+        hr = IDxDiagContainer_EnumPropNames(child, index, property, buffersize);
+        if (hr == E_INVALIDARG)
+        {
+            /* We should get here when index is one more than the maximum index value. */
+            ok(propcount == index,
+               "Expected IDxDiagContainer::EnumPropNames to return E_INVALIDARG "
+               "on the last index %d, got 0x%08x\n", index, hr);
+            ok(!memcmp(property, testW, sizeof(testW)),
+               "Expected the property buffer to be unchanged, got %s\n", wine_dbgstr_w(property));
+            break;
+        }
+        else if (hr == DXDIAG_E_INSUFFICIENT_BUFFER)
+        {
+            WCHAR temp[256];
+
+            ok(property[0] == '\0',
+               "Expected the property buffer string to be empty, got %s\n", wine_dbgstr_w(property));
+            hr = IDxDiagContainer_EnumPropNames(child, index, temp, sizeof(temp)/sizeof(WCHAR));
+            ok(hr == S_OK,
+               "Expected IDxDiagContainer::EnumPropNames to return S_OK, got 0x%08x\n", hr);
+
+            /* Show that the DirectX SDK's stipulation that the buffer be at
+             * least 256 characters long is a mere suggestion, and smaller sizes
+             * can be acceptable also. IDxDiagContainer::EnumPropNames doesn't
+             * provide a way of getting the exact size required, so the buffersize
+             * value will be iterated to at most 256 characters. */
+            for (buffersize = 2; buffersize <= 256; buffersize++)
+            {
+                memcpy(property, testW, sizeof(testW));
+                hr = IDxDiagContainer_EnumPropNames(child, index, property, buffersize);
+                if (hr != DXDIAG_E_INSUFFICIENT_BUFFER)
+                    break;
+
+                ok(!memcmp(temp, property, sizeof(WCHAR)*(buffersize - 1)),
+                   "Expected truncated property name string, got %s\n", wine_dbgstr_w(property));
+            }
+
+            ok(hr == S_OK,
+               "Expected IDxDiagContainer::EnumPropNames to return S_OK, "
+               "got hr = 0x%08x, buffersize = %d\n", hr, buffersize);
+            if (hr == S_OK)
+                trace("child[%d] = %s, length = %d\n", index, wine_dbgstr_w(property), buffersize);
+        }
+        else
+        {
+            ok(0, "IDxDiagContainer::EnumPropNames unexpectedly returned 0x%08x\n", hr);
+            break;
+        }
+    }
+
     IDxDiagContainer_Release(child);
 
 cleanup:




More information about the wine-cvs mailing list