[PATCH 3/4] d3dx9: Handle short parameter in d3dx_set_shader_const_state().

Paul Gofman gofmanp at gmail.com
Wed Feb 13 11:29:58 CST 2019


The issue is spotted in https://bugs.winehq.org/show_bug.cgi?id=46553,
while fixing it alone is reported not to affect the bug.

Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
 dlls/d3dx9_36/effect.c       | 58 +++++++++++++++++++++++++++++-------
 dlls/d3dx9_36/tests/effect.c | 10 +++----
 2 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index b72e9ea6ca..e2670f37c9 100644
--- a/dlls/d3dx9_36/effect.c
+++ b/dlls/d3dx9_36/effect.c
@@ -2981,7 +2981,12 @@ static HRESULT d3dx_set_shader_const_state(struct ID3DXEffectImpl *effect, enum
         {D3DXPT_BOOL,  sizeof(BOOL),      "SCT_PSBOOL"},
         {D3DXPT_INT,   sizeof(int) * 4,   "SCT_PSINT"},
     };
+
+    BOOL is_heap_buffer = FALSE;
     unsigned int element_count;
+    void *buffer = value_ptr;
+    D3DXVECTOR4 value;
+    HRESULT ret;
 
     if (op < 0 || op > SCT_PSINT)
     {
@@ -2995,28 +3000,61 @@ static HRESULT d3dx_set_shader_const_state(struct ID3DXEffectImpl *effect, enum
         FIXME("Unexpected param type %u.\n", param->type);
         return D3DERR_INVALIDCALL;
     }
-    if (param->bytes % const_tbl[op].elem_size != 0)
+
+    if (param->bytes % const_tbl[op].elem_size)
     {
-        FIXME("Unexpected param size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns);
-        return D3DERR_INVALIDCALL;
+        TRACE("Parameter size %u, rows %u, cols %u.\n", param->bytes, param->rows, param->columns);
+
+        if (++element_count > 1)
+        {
+            WARN("Setting %u elements.\n", element_count);
+            buffer = HeapAlloc(GetProcessHeap(), 0, const_tbl[op].elem_size * element_count);
+            if (!buffer)
+            {
+                ERR("Out of memory.\n");
+                return E_OUTOFMEMORY;
+            }
+            is_heap_buffer = TRUE;
+        }
+        else
+        {
+            assert(const_tbl[op].elem_size <= sizeof(value));
+            buffer = &value;
+        }
+        memcpy(buffer, value_ptr, param->bytes);
+        memset((unsigned char *)buffer + param->bytes, 0,
+                const_tbl[op].elem_size * element_count - param->bytes);
     }
 
     switch (op)
     {
         case SCT_VSFLOAT:
-            return SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)value_ptr, element_count);
+            ret = SET_D3D_STATE(effect, SetVertexShaderConstantF, index, (const float *)buffer, element_count);
+            break;
         case SCT_VSBOOL:
-            return SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)value_ptr, element_count);
+            ret = SET_D3D_STATE(effect, SetVertexShaderConstantB, index, (const BOOL *)buffer, element_count);
+            break;
         case SCT_VSINT:
-            return SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)value_ptr, element_count);
+            ret = SET_D3D_STATE(effect, SetVertexShaderConstantI, index, (const int *)buffer, element_count);
+            break;
         case SCT_PSFLOAT:
-            return SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)value_ptr, element_count);
+            ret = SET_D3D_STATE(effect, SetPixelShaderConstantF, index, (const float *)buffer, element_count);
+            break;
         case SCT_PSBOOL:
-            return SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)value_ptr, element_count);
+            ret = SET_D3D_STATE(effect, SetPixelShaderConstantB, index, (const BOOL *)buffer, element_count);
+            break;
         case SCT_PSINT:
-            return SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)value_ptr, element_count);
+            ret = SET_D3D_STATE(effect, SetPixelShaderConstantI, index, (const int *)buffer, element_count);
+            break;
+        default:
+            ret = D3DERR_INVALIDCALL;
+            break;
     }
-    return D3D_OK;
+
+    if (is_heap_buffer)
+        HeapFree(GetProcessHeap(), 0, buffer);
+
+    return ret;
 }
 
 static BOOL quick_is_state_dirty(struct d3dx_pass *pass, struct d3dx_state *state, BOOL update_all)
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c
index 9501848c4d..5a9760802f 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -3113,7 +3113,7 @@ static void test_effect_states(IDirect3DDevice9 *device)
     test_effect_clear_vconsts(device);
 
     hr = effect->lpVtbl->BeginPass(effect, 0);
-    todo_wine ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
+    ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
 
     hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLDMATRIX(1), &mat);
     ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
@@ -3158,11 +3158,11 @@ static void test_effect_states(IDirect3DDevice9 *device)
      * contain garbage data on native. */
     hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, &fvect.x, 1);
     ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
-    todo_wine ok(fvect.x == 3.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n",
+    ok(fvect.x == 3.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n",
             fvect.x, fvect.y, fvect.z, fvect.w);
     hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 2, &fvect.x, 1);
     ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
-    todo_wine ok(fvect.x == 1.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n",
+    ok(fvect.x == 1.0f, "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n",
             fvect.x, fvect.y, fvect.z, fvect.w);
 
     hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 3, &fvect.x, 1);
@@ -3173,7 +3173,7 @@ static void test_effect_states(IDirect3DDevice9 *device)
 
     hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 4, &fvect.x, 1);
     ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
-    todo_wine ok(fvect.x == 4.0f && fvect.y == 4.0f && fvect.z == 4.0f && fvect.w == 4.0f,
+    ok(fvect.x == 4.0f && fvect.y == 4.0f && fvect.z == 4.0f && fvect.w == 4.0f,
             "Got unexpected vertex shader constant (%.8e, %.8e, %.8e, %.8e).\n",
             fvect.x, fvect.y, fvect.z, fvect.w);
     hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 5, &fvect.x, 1);
@@ -3193,7 +3193,7 @@ static void test_effect_states(IDirect3DDevice9 *device)
             fvect.x, fvect.y, fvect.z, fvect.w);
 
     hr = effect->lpVtbl->EndPass(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
+    ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_BLENDOP, &value);
     ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr);
     ok(value == 2, "Got result %u, expected %u\n", value, 2);
-- 
2.20.1




More information about the wine-devel mailing list