d3d11: Validate offsets and sizes in shader_parse_signature() (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-05-24 19:46:43 +02:00 committed by Alexandre Julliard
parent 994c5618b1
commit b1665527af
3 changed files with 41 additions and 5 deletions

View File

@ -85,9 +85,9 @@ static inline void read_dword(const char **ptr, DWORD *d)
*ptr += sizeof(*d);
}
static inline BOOL require_space(size_t offset, size_t size, size_t data_size)
static inline BOOL require_space(size_t offset, size_t count, size_t size, size_t data_size)
{
return data_size - offset >= size;
return !count || (data_size - offset) / count >= size;
}
void skip_dword_unknown(const char **ptr, unsigned int count) DECLSPEC_HIDDEN;

View File

@ -78,6 +78,25 @@ static HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length, st
return hr;
}
static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
{
size_t len, max_len;
if (offset >= data_size)
{
WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size);
return NULL;
}
max_len = data_size - offset;
len = strnlen(data + offset, max_len);
if (len == max_len)
return NULL;
return data + offset;
}
HRESULT shader_parse_signature(const char *data, DWORD data_size, struct wined3d_shader_signature *s)
{
struct wined3d_shader_signature_element *e;
@ -85,11 +104,23 @@ HRESULT shader_parse_signature(const char *data, DWORD data_size, struct wined3d
unsigned int i;
DWORD count;
if (!require_space(0, 2, sizeof(DWORD), data_size))
{
WARN("Invalid data size %#x.\n", data_size);
return E_INVALIDARG;
}
read_dword(&ptr, &count);
TRACE("%u elements\n", count);
skip_dword_unknown(&ptr, 1);
if (!require_space(ptr - data, count, 6 * sizeof(DWORD), data_size))
{
WARN("Invalid count %#x (data size %#x).\n", count, data_size);
return E_INVALIDARG;
}
e = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*e));
if (!e)
{
@ -102,7 +133,12 @@ HRESULT shader_parse_signature(const char *data, DWORD data_size, struct wined3d
UINT name_offset;
read_dword(&ptr, &name_offset);
e[i].semantic_name = data + name_offset;
if (!(e[i].semantic_name = shader_get_string(data, data_size, name_offset)))
{
WARN("Invalid name offset %#x (data size %#x).\n", name_offset, data_size);
HeapFree(GetProcessHeap(), 0, e);
return E_INVALIDARG;
}
read_dword(&ptr, &e[i].semantic_idx);
read_dword(&ptr, &e[i].sysval_semantic);
read_dword(&ptr, &e[i].component_type);

View File

@ -751,7 +751,7 @@ HRESULT parse_dxbc(const char *data, SIZE_T data_size,
read_dword(&ptr, &chunk_offset);
TRACE("chunk %u at offset %#x\n", i, chunk_offset);
if (chunk_offset >= data_size || !require_space(chunk_offset, 2 * sizeof(DWORD), data_size))
if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(DWORD), data_size))
{
WARN("Invalid chunk offset %#x (data size %#lx).\n", chunk_offset, data_size);
return E_FAIL;
@ -762,7 +762,7 @@ HRESULT parse_dxbc(const char *data, SIZE_T data_size,
read_dword(&chunk_ptr, &chunk_tag);
read_dword(&chunk_ptr, &chunk_size);
if (!require_space(chunk_ptr - data, chunk_size, data_size))
if (!require_space(chunk_ptr - data, 1, chunk_size, data_size))
{
WARN("Invalid chunk size %#x (data size %#lx, chunk offset %#x).\n", chunk_size, data_size, chunk_offset);
return E_FAIL;