d3d10: Validate offsets in parse_shader() (AFL).

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2016-07-10 15:09:19 +02:00 committed by Alexandre Julliard
parent c4ccdb2484
commit 7f6520a2bb
1 changed files with 23 additions and 12 deletions

View File

@ -475,12 +475,11 @@ static HRESULT shader_chunk_handler(const char *data, DWORD data_size, DWORD tag
return S_OK; 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; ID3D10Device *device = v->effect->device;
const char *ptr = data;
DWORD dxbc_size; DWORD dxbc_size;
const char *ptr;
HRESULT hr; HRESULT hr;
if (v->effect->used_shader_current >= v->effect->used_shader_count) 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_shaders[v->effect->used_shader_current] = v;
++v->effect->used_shader_current; ++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); read_dword(&ptr, &dxbc_size);
TRACE("dxbc size: %#x\n", 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. */ /* We got a shader VertexShader vs = NULL, so it is fine to skip this. */
if (!dxbc_size) return S_OK; if (!dxbc_size) return S_OK;
@ -1304,6 +1314,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
HRESULT hr; HRESULT hr;
struct d3d10_effect *effect = o->pass->technique->effect; struct d3d10_effect *effect = o->pass->technique->effect;
ID3D10Effect *e = &effect->ID3D10Effect_iface; ID3D10Effect *e = &effect->ID3D10Effect_iface;
struct d3d10_effect_variable *v;
DWORD tmp, variable_idx = 0; DWORD tmp, variable_idx = 0;
const char *name; const char *name;
size_t name_len; 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); read_dword(&data_ptr, &offset);
TRACE("Effect object starts at offset %#x.\n", 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); v = &effect->anonymous_shaders[effect->anonymous_shader_current].shader;
if (FAILED(hr)) return hr; variable = &v->ID3D10EffectVariable_iface;
variable = &effect->anonymous_shaders[effect->anonymous_shader_current].shader.ID3D10EffectVariable_iface;
++effect->anonymous_shader_current; ++effect->anonymous_shader_current;
switch (o->type) 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_VERTEXSHADER:
case D3D10_EOT_PIXELSHADER: case D3D10_EOT_PIXELSHADER:
case D3D10_EOT_GEOMETRYSHADER: 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; return hr;
break; break;
@ -1800,8 +1811,8 @@ static HRESULT parse_fx10_local_variable(const char *data, size_t data_size,
read_dword(ptr, &shader_offset); read_dword(ptr, &shader_offset);
TRACE("Shader offset: %#x.\n", shader_offset); TRACE("Shader offset: %#x.\n", shader_offset);
hr = parse_shader(&var->ID3D10EffectVariable_iface, data + shader_offset); if (FAILED(hr = parse_fx10_shader(data, data_size, shader_offset, var)))
if (FAILED(hr)) return hr; return hr;
} }
break; break;