From b42fe709d6db16a7f13f708e5a5c9a5d802cabad Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Fri, 13 Jun 2014 15:08:51 +0200 Subject: [PATCH] wined3d: Validate and handle query size parameter. --- dlls/d3d9/query.c | 5 ++- dlls/d3d9/tests/device.c | 10 +++--- dlls/wined3d/query.c | 73 +++++++++++++++++++++------------------- 3 files changed, 48 insertions(+), 40 deletions(-) diff --git a/dlls/d3d9/query.c b/dlls/d3d9/query.c index bb78d7fe9fa..6af89f64feb 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 ffad0d65ed2..ab52e19af4f 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -4631,7 +4631,7 @@ static void test_occlusion_query_states(void) if (!broken_occlusion) ok(data.word[0] == (WORD)expected, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]); - todo_wine ok(data.word[1] == 0xffff, + ok(data.word[1] == 0xffff, "data was modified outside of the expected size (0x%.8x).\n", data.dword[0]); memset(&data, 0xf0, sizeof(data)); @@ -4652,7 +4652,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.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]); + ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]); /* This crashes on Windows. */ if (0) @@ -4744,7 +4744,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(freq[1] == 0xffffffff, + ok(freq[1] == 0xffffffff, "freq was modified outside of the expected size (0x%.8x).\n", freq[1]); hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); @@ -4788,7 +4788,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(timestamp[1] == 0xffffffff, + ok(timestamp[1] == 0xffffffff, "timestamp was modified outside of the expected size (0x%.8x).\n", timestamp[1]); @@ -4812,7 +4812,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(disjoint[1] == 0xffff, + ok(disjoint[1] == 0xffff, "disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]); 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 ef1ab17c0da..b01e124cd4f 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -295,19 +295,23 @@ 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) +{ + memcpy(out, result, min(out_size, 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 +320,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 +335,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 +356,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 +376,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 +398,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 +545,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 +558,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, ×tamp, 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, ×tamp, sizeof(timestamp)); return S_OK; } @@ -569,12 +579,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, ×tamp)); checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); - *u64data = timestamp; + fill_query_data(data, size, ×tamp, sizeof(timestamp)); } res = S_OK; } @@ -629,11 +639,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 +651,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; }