From 7f6520a2bb662d9e3caac2f4dc08880951269c9f Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Sun, 10 Jul 2016 15:09:19 +0200 Subject: [PATCH] d3d10: Validate offsets in parse_shader() (AFL). Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3d10/effect.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index ff00aa12c99..4736fa93e0e 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c @@ -475,12 +475,11 @@ static HRESULT shader_chunk_handler(const char *data, DWORD data_size, DWORD tag return S_OK; } -static HRESULT parse_shader(ID3D10EffectVariable *variable, const char *data) +static HRESULT parse_fx10_shader(const char *data, size_t data_size, DWORD offset, struct d3d10_effect_variable *v) { - struct d3d10_effect_variable *v = impl_from_ID3D10EffectVariable(variable); ID3D10Device *device = v->effect->device; - const char *ptr = data; DWORD dxbc_size; + const char *ptr; HRESULT hr; if (v->effect->used_shader_current >= v->effect->used_shader_count) @@ -492,11 +491,22 @@ static HRESULT parse_shader(ID3D10EffectVariable *variable, const char *data) v->effect->used_shaders[v->effect->used_shader_current] = v; ++v->effect->used_shader_current; - if (!ptr) return S_OK; + if (offset >= data_size || !require_space(offset, 1, sizeof(dxbc_size), data_size)) + { + WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size); + return E_FAIL; + } + ptr = data + offset; read_dword(&ptr, &dxbc_size); TRACE("dxbc size: %#x\n", dxbc_size); + if (!require_space(ptr - data, 1, dxbc_size, data_size)) + { + WARN("Invalid dxbc size %#x (data size %#lx, offset %#x).\n", offset, (long)data_size, offset); + return E_FAIL; + } + /* We got a shader VertexShader vs = NULL, so it is fine to skip this. */ if (!dxbc_size) return S_OK; @@ -1304,6 +1314,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, HRESULT hr; struct d3d10_effect *effect = o->pass->technique->effect; ID3D10Effect *e = &effect->ID3D10Effect_iface; + struct d3d10_effect_variable *v; DWORD tmp, variable_idx = 0; const char *name; size_t name_len; @@ -1431,12 +1442,12 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, read_dword(&data_ptr, &offset); TRACE("Effect object starts at offset %#x.\n", offset); - data_ptr = data + offset; + if (FAILED(hr = parse_fx10_anonymous_shader(effect, + &effect->anonymous_shaders[effect->anonymous_shader_current], o->type))) + return hr; - hr = parse_fx10_anonymous_shader(effect, &effect->anonymous_shaders[effect->anonymous_shader_current], o->type); - if (FAILED(hr)) return hr; - - variable = &effect->anonymous_shaders[effect->anonymous_shader_current].shader.ID3D10EffectVariable_iface; + v = &effect->anonymous_shaders[effect->anonymous_shader_current].shader; + variable = &v->ID3D10EffectVariable_iface; ++effect->anonymous_shader_current; switch (o->type) @@ -1444,7 +1455,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, case D3D10_EOT_VERTEXSHADER: case D3D10_EOT_PIXELSHADER: case D3D10_EOT_GEOMETRYSHADER: - if (FAILED(hr = parse_shader(variable, data_ptr))) + if (FAILED(hr = parse_fx10_shader(data, data_size, offset, v))) return hr; break; @@ -1800,8 +1811,8 @@ static HRESULT parse_fx10_local_variable(const char *data, size_t data_size, read_dword(ptr, &shader_offset); TRACE("Shader offset: %#x.\n", shader_offset); - hr = parse_shader(&var->ID3D10EffectVariable_iface, data + shader_offset); - if (FAILED(hr)) return hr; + if (FAILED(hr = parse_fx10_shader(data, data_size, shader_offset, var))) + return hr; } break;