d3d10: 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:
parent
b1665527af
commit
22d52ed59d
|
@ -294,9 +294,9 @@ static inline void write_dword(char **ptr, DWORD d)
|
||||||
*ptr += sizeof(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 *location, const char **ptr, unsigned int count) DECLSPEC_HIDDEN;
|
void skip_dword_unknown(const char *location, const char **ptr, unsigned int count) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -267,6 +267,25 @@ static BOOL copy_name(const char *ptr, char **name)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT shader_parse_signature(const char *data, DWORD data_size, struct d3d10_effect_shader_signature *s)
|
static HRESULT shader_parse_signature(const char *data, DWORD data_size, struct d3d10_effect_shader_signature *s)
|
||||||
{
|
{
|
||||||
D3D10_SIGNATURE_PARAMETER_DESC *e;
|
D3D10_SIGNATURE_PARAMETER_DESC *e;
|
||||||
|
@ -274,11 +293,23 @@ static HRESULT shader_parse_signature(const char *data, DWORD data_size, struct
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
DWORD count;
|
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);
|
read_dword(&ptr, &count);
|
||||||
TRACE("%u elements\n", count);
|
TRACE("%u elements\n", count);
|
||||||
|
|
||||||
skip_dword_unknown("shader signature", &ptr, 1);
|
skip_dword_unknown("shader signature", &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));
|
e = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*e));
|
||||||
if (!e)
|
if (!e)
|
||||||
{
|
{
|
||||||
|
@ -292,7 +323,12 @@ static HRESULT shader_parse_signature(const char *data, DWORD data_size, struct
|
||||||
UINT mask;
|
UINT mask;
|
||||||
|
|
||||||
read_dword(&ptr, &name_offset);
|
read_dword(&ptr, &name_offset);
|
||||||
e[i].SemanticName = data + name_offset;
|
if (!(e[i].SemanticName = 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].SemanticIndex);
|
read_dword(&ptr, &e[i].SemanticIndex);
|
||||||
read_dword(&ptr, &e[i].SystemValueType);
|
read_dword(&ptr, &e[i].SystemValueType);
|
||||||
read_dword(&ptr, &e[i].ComponentType);
|
read_dword(&ptr, &e[i].ComponentType);
|
||||||
|
|
|
@ -217,7 +217,7 @@ HRESULT parse_dxbc(const char *data, SIZE_T data_size,
|
||||||
read_dword(&ptr, &chunk_offset);
|
read_dword(&ptr, &chunk_offset);
|
||||||
TRACE("chunk %u at offset %#x\n", i, 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);
|
WARN("Invalid chunk offset %#x (data size %#lx).\n", chunk_offset, data_size);
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
@ -228,7 +228,7 @@ HRESULT parse_dxbc(const char *data, SIZE_T data_size,
|
||||||
read_dword(&chunk_ptr, &chunk_tag);
|
read_dword(&chunk_ptr, &chunk_tag);
|
||||||
read_dword(&chunk_ptr, &chunk_size);
|
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);
|
WARN("Invalid chunk size %#x (data size %#lx, chunk offset %#x).\n", chunk_size, data_size, chunk_offset);
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
Loading…
Reference in New Issue