[PATCH 2/6] wined3d: Validate and handle query size parameter.

Matteo Bruni mbruni at codeweavers.com
Thu May 1 11:37:37 CDT 2014


---
 dlls/d3d9/query.c        |  5 +++-
 dlls/d3d9/tests/device.c | 10 +++----
 dlls/wined3d/query.c     | 75 ++++++++++++++++++++++++++----------------------
 3 files changed, 50 insertions(+), 40 deletions(-)

diff --git a/dlls/d3d9/query.c b/dlls/d3d9/query.c
index bb78d7f..6af89f6 100644
--- a/dlls/d3d9/query.c
+++ b/dlls/d3d9/query.c
@@ -153,8 +153,11 @@ static HRESULT WINAPI d3d9_query_GetData(IDirect3DQuery9 *iface, void *data, DWO
     {
         struct wined3d_query_data_timestamp_disjoint data_disjoint;
 
+        if (size > sizeof(data_disjoint.disjoint))
+            size = sizeof(data_disjoint.disjoint);
+
         hr = wined3d_query_get_data(query->wined3d_query, &data_disjoint, sizeof(data_disjoint), flags);
-        *(BOOL *)data = data_disjoint.disjoint;
+        memcpy(data, &data_disjoint.disjoint, size);
     }
     else
     {
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index f695cc2..870221c 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -3854,7 +3854,7 @@ static void test_occlusion_query_states(void)
     hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
     ok(*(WORD *)&data == 1, "Occlusion query returned an unexpected result (0x%.8x).\n", data);
-    todo_wine ok(*((WORD *)&data + 1) == 0xffff,
+    ok(*((WORD *)&data + 1) == 0xffff,
             "data was modified outside of the expected size (0x%.8x).\n", data);
     hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
@@ -3877,7 +3877,7 @@ static void test_occlusion_query_states(void)
     memset(&data, 0xff, sizeof(data));
     hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
-    todo_wine ok(data == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data);
+    ok(data == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data);
 
     /* This crashes on Windows. */
     if (0)
@@ -3961,7 +3961,7 @@ static void test_timestamp_query(void)
     memset(&freq, 0xff, sizeof(freq));
     hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(DWORD), D3DGETDATA_FLUSH);
     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
-    todo_wine ok(*((DWORD *)&freq + 1) == 0xffffffff,
+    ok(*((DWORD *)&freq + 1) == 0xffffffff,
             "freq was modified outside of the expected size (0x%.8x).\n", *((DWORD *)&freq + 1));
     hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
@@ -4005,7 +4005,7 @@ static void test_timestamp_query(void)
     memset(&timestamp, 0xff, sizeof(timestamp));
     hr = IDirect3DQuery9_GetData(query, &timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
-    todo_wine ok(*((DWORD *)&timestamp + 1) == 0xffffffff,
+    ok(*((DWORD *)&timestamp + 1) == 0xffffffff,
             "timestamp was modified outside of the expected size (0x%.8x).\n",
             *((DWORD *)&timestamp + 1));
 
@@ -4029,7 +4029,7 @@ static void test_timestamp_query(void)
     memset(&disjoint, 0xff, sizeof(disjoint));
     hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
-    todo_wine ok(*((WORD *)&disjoint + 1) == 0xffff,
+    ok(*((WORD *)&disjoint + 1) == 0xffff,
             "disjoint was modified outside of the expected size (0x%.8x).\n", disjoint);
     hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index ef1ab17..ffc7fad 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -295,19 +295,25 @@ HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags)
     return query->query_ops->query_issue(query, flags);
 }
 
+static void fill_query_data(void *out, unsigned int out_size, const void *result, unsigned int result_size)
+{
+    unsigned int size = min(out_size, result_size);
+
+    memcpy(out, result, size);
+}
+
 static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query,
-        void *pData, DWORD dwSize, DWORD flags)
+        void *data, DWORD size, DWORD flags)
 {
     struct wined3d_occlusion_query *oq = query->extendedData;
     struct wined3d_device *device = query->device;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     struct wined3d_context *context;
-    DWORD* data = pData;
     GLuint available;
     GLuint samples;
     HRESULT res;
 
-    TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, flags %#x.\n", query, pData, dwSize, flags);
+    TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags);
 
     if (!oq->context)
         query->state = QUERY_CREATED;
@@ -316,7 +322,8 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query,
     {
         /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
         TRACE("Query wasn't yet started, returning S_OK\n");
-        if(data) *data = 0;
+        samples = 0;
+        fill_query_data(data, size, &samples, sizeof(samples));
         return S_OK;
     }
 
@@ -330,14 +337,16 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query,
     if (!gl_info->supported[ARB_OCCLUSION_QUERY])
     {
         WARN("%p Occlusion queries not supported. Returning 1.\n", query);
-        *data = 1;
+        samples = 1;
+        fill_query_data(data, size, &samples, sizeof(samples));
         return S_OK;
     }
 
     if (oq->context->tid != GetCurrentThreadId())
     {
         FIXME("%p Wrong thread, returning 1.\n", query);
-        *data = 1;
+        samples = 1;
+        fill_query_data(data, size, &samples, sizeof(samples));
         return S_OK;
     }
 
@@ -349,12 +358,12 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query,
 
     if (available)
     {
-        if (data)
+        if (size)
         {
             GL_EXTCALL(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_ARB, &samples));
             checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
             TRACE("Returning %d samples.\n", samples);
-            *data = samples;
+            fill_query_data(data, size, &samples, sizeof(samples));
         }
         res = S_OK;
     }
@@ -369,19 +378,20 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query,
 }
 
 static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query,
-        void *pData, DWORD dwSize, DWORD flags)
+        void *data, DWORD size, DWORD flags)
 {
     struct wined3d_event_query *event_query = query->extendedData;
-    BOOL *data = pData;
+    BOOL signaled;
     enum wined3d_event_query_result ret;
 
-    TRACE("query %p, pData %p, dwSize %#x, flags %#x.\n", query, pData, dwSize, flags);
+    TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags);
 
-    if (!pData || !dwSize) return S_OK;
+    if (!data || !size) return S_OK;
     if (!event_query)
     {
         WARN("Event query not supported by GL, reporting GPU idle.\n");
-        *data = TRUE;
+        signaled = TRUE;
+        fill_query_data(data, size, &signaled, sizeof(signaled));
         return S_OK;
     }
 
@@ -390,16 +400,19 @@ static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query,
     {
         case WINED3D_EVENT_QUERY_OK:
         case WINED3D_EVENT_QUERY_NOT_STARTED:
-            *data = TRUE;
+            signaled = TRUE;
+            fill_query_data(data, size, &signaled, sizeof(signaled));
             break;
 
         case WINED3D_EVENT_QUERY_WAITING:
-            *data = FALSE;
+            signaled = FALSE;
+            fill_query_data(data, size, &signaled, sizeof(signaled));
             break;
 
         case WINED3D_EVENT_QUERY_WRONG_THREAD:
             FIXME("(%p) Wrong thread, reporting GPU idle.\n", query);
-            *data = TRUE;
+            signaled = TRUE;
+            fill_query_data(data, size, &signaled, sizeof(signaled));
             break;
 
         case WINED3D_EVENT_QUERY_ERROR:
@@ -534,12 +547,11 @@ static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query,
     struct wined3d_device *device = query->device;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     struct wined3d_context *context;
-    UINT64 *u64data = data;
     GLuint available;
     GLuint64 timestamp;
     HRESULT res;
 
-    TRACE("(%p) : type D3DQUERY_TIMESTAMP, data %p, size %#x, flags %#x.\n", query, data, size, flags);
+    TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags);
 
     if (!tq->context)
         query->state = QUERY_CREATED;
@@ -548,16 +560,16 @@ static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query,
     {
         /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves. */
         TRACE("Query wasn't yet started, returning S_OK.\n");
-        if (u64data)
-            *u64data = 0;
+        timestamp = 0;
+        fill_query_data(data, size, &timestamp, sizeof(timestamp));
         return S_OK;
     }
 
     if (tq->context->tid != GetCurrentThreadId())
     {
         FIXME("%p Wrong thread, returning 1.\n", query);
-        if (u64data)
-            *u64data = 1;
+        timestamp = 1;
+        fill_query_data(data, size, &timestamp, sizeof(timestamp));
         return S_OK;
     }
 
@@ -569,12 +581,12 @@ static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query,
 
     if (available)
     {
-        if (u64data)
+        if (size)
         {
             GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT_ARB, &timestamp));
             checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
             TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp));
-            *u64data = timestamp;
+            fill_query_data(data, size, &timestamp, sizeof(timestamp));
         }
         res = S_OK;
     }
@@ -629,11 +641,11 @@ static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DW
 static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_query *query,
         void *data, DWORD size, DWORD flags)
 {
-    TRACE("(%p) : type D3DQUERY_TIMESTAMP_DISJOINT, data %p, size %#x, flags %#x.\n", query, data, size, flags);
+    TRACE("query %p, data %p, size %#x, flags %#x.\n", query, data, size, flags);
 
     if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT)
     {
-        struct wined3d_query_data_timestamp_disjoint *disjoint_data = data;
+        static const struct wined3d_query_data_timestamp_disjoint disjoint_data = {FALSE, 1000 * 1000 * 1000};
 
         if (query->state == QUERY_BUILDING)
         {
@@ -641,18 +653,13 @@ static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_quer
             return S_FALSE;
         }
 
-        if (disjoint_data)
-        {
-            disjoint_data->disjoint = FALSE;
-            disjoint_data->frequency = 1000 * 1000 * 1000;
-        }
+        fill_query_data(data, size, &disjoint_data, sizeof(disjoint_data));
     }
     else
     {
-        UINT64 *u64data = data;
+        static const UINT64 freq = 1000 * 1000 * 1000;
 
-        if (u64data)
-            *u64data = 1000 * 1000 * 1000;
+        fill_query_data(data, size, &freq, sizeof(freq));
     }
     return S_OK;
 }
-- 
1.8.3.2




More information about the wine-patches mailing list