From: Rico Schüller Subject: [PATCH 1/2] wined3d: Add argument check for Type to Get/SetTextureStageState(). Message-Id: <4C8C908C.7070006@web.de> Date: Sun, 12 Sep 2010 10:34:20 +0200 Hi, this patch add in argument check for the Type to Get/SetTextureStageState(). It seems that some apps simply loop trough all values, which could crash because we index the array with a to high index (see bug 24249). I've not added a test, because you could get an unhandled page fault on read access in the case of GetTextureStageState() (it depends on the type and state value). Cheers Rico --- dlls/d3d8/device.c | 26 ++++++++++++++++++++++---- dlls/d3d9/device.c | 18 ++++++++++++++++-- dlls/ddraw/device.c | 9 ++++++--- dlls/wined3d/device.c | 23 ++++++++++++++++++++--- 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index c547da4..f54f043 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1575,13 +1575,22 @@ tss_lookup[] = {FALSE, WINED3DTSS_RESULTARG}, /* 28, D3DTSS_RESULTARG */ }; -static HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) { +static HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue) +{ IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; - const struct tss_lookup *l = &tss_lookup[Type]; + const struct tss_lookup *l; HRESULT hr; TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, Stage, Type, pValue); + if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup)) + { + WARN("Invalid Type %#x passed.\n", Type); + return D3D_OK; + } + + l = &tss_lookup[Type]; + wined3d_mutex_lock(); if (l->sampler_state) hr = IWineD3DDevice_GetSamplerState(This->WineD3DDevice, Stage, l->state, pValue); else hr = IWineD3DDevice_GetTextureStageState(This->WineD3DDevice, Stage, l->state, pValue); @@ -1590,13 +1599,22 @@ static HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVI return hr; } -static HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) { +static HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) +{ IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface; - const struct tss_lookup *l = &tss_lookup[Type]; + const struct tss_lookup *l; HRESULT hr; TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, Stage, Type, Value); + if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup)) + { + WARN("Invalid Type %#x passed.\n", Type); + return D3D_OK; + } + + l = &tss_lookup[Type]; + wined3d_mutex_lock(); if (l->sampler_state) hr = IWineD3DDevice_SetSamplerState(This->WineD3DDevice, Stage, l->state, Value); else hr = IWineD3DDevice_SetTextureStageState(This->WineD3DDevice, Stage, l->state, Value); diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index af9cc48..c788b98 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1681,12 +1681,19 @@ static const WINED3DTEXTURESTAGESTATETYPE tss_lookup[] = WINED3DTSS_CONSTANT, /* 32, D3DTSS_CONSTANT */ }; -static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVICE9EX iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) { +static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVICE9EX iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue) +{ IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, Stage, Type, pValue); + if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup)) + { + WARN("Invalid Type %#x passed.\n", Type); + return D3D_OK; + } + wined3d_mutex_lock(); hr = IWineD3DDevice_GetTextureStageState(This->WineD3DDevice, Stage, tss_lookup[Type], pValue); wined3d_mutex_unlock(); @@ -1694,12 +1701,19 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetTextureStageState(LPDIRECT3DDEVI return hr; } -static HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(LPDIRECT3DDEVICE9EX iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) { +static HRESULT WINAPI IDirect3DDevice9Impl_SetTextureStageState(LPDIRECT3DDEVICE9EX iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) +{ IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; TRACE("iface %p, stage %u, state %#x, value %#x.\n", iface, Stage, Type, Value); + if (Type >= sizeof(tss_lookup) / sizeof(*tss_lookup)) + { + WARN("Invalid Type %#x passed.\n", Type); + return D3D_OK; + } + wined3d_mutex_lock(); hr = IWineD3DDevice_SetTextureStageState(This->WineD3DDevice, Stage, tss_lookup[Type], Value); wined3d_mutex_unlock(); diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 95526bd..69e94d7 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -4871,7 +4871,7 @@ IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface, { IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface; HRESULT hr; - const struct tss_lookup *l = &tss_lookup[TexStageStateType]; + const struct tss_lookup *l; TRACE("iface %p, stage %u, state %#x, value %p.\n", iface, Stage, TexStageStateType, State); @@ -4882,10 +4882,11 @@ IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface, if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS) { WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType); - *State = 0; return DD_OK; } + l = &tss_lookup[TexStageStateType]; + EnterCriticalSection(&ddraw_cs); if (l->sampler_state) @@ -5004,7 +5005,7 @@ IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface, DWORD State) { IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface; - const struct tss_lookup *l = &tss_lookup[TexStageStateType]; + const struct tss_lookup *l; HRESULT hr; TRACE("iface %p, stage %u, state %#x, value %#x.\n", @@ -5016,6 +5017,8 @@ IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface, return DD_OK; } + l = &tss_lookup[TexStageStateType]; + EnterCriticalSection(&ddraw_cs); if (l->sampler_state) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 4e59769..c55b101 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4193,13 +4193,20 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, * Get / Set Texture Stage States * TODO: Verify against dx9 definitions *****/ -static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) { +static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - DWORD oldValue = This->updateStateBlock->textureState[Stage][Type]; const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + DWORD oldValue; TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value); + if (Type > WINED3D_HIGHEST_TEXTURE_STATE) + { + WARN("Invalid Type %d passed.\n", Type); + return WINED3D_OK; + } + if (Stage >= gl_info->limits.texture_stages) { WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n", @@ -4207,6 +4214,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *if return WINED3D_OK; } + oldValue = This->updateStateBlock->textureState[Stage][Type]; This->updateStateBlock->changed.textureState[Stage] |= 1 << Type; This->updateStateBlock->textureState[Stage][Type] = Value; @@ -4270,9 +4278,18 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *if return WINED3D_OK; } -static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) { +static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD *pValue) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + + if (Type > WINED3D_HIGHEST_TEXTURE_STATE) + { + WARN("Invalid Type %d passed.\n", Type); + return WINED3D_OK; + } + TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]); + *pValue = This->updateStateBlock->textureState[Stage][Type]; return WINED3D_OK; }