From b1665527af5d7b7c402597412cf14b59fbcddd61 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 24 May 2016 19:46:43 +0200 Subject: [PATCH] d3d11: Validate offsets and sizes in shader_parse_signature() (AFL). Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3d11/d3d11_private.h | 4 ++-- dlls/d3d11/shader.c | 38 +++++++++++++++++++++++++++++++++++++- dlls/d3d11/utils.c | 4 ++-- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 41fd89d0c36..b3638c38d99 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -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; diff --git a/dlls/d3d11/shader.c b/dlls/d3d11/shader.c index f8647ff763e..a88c8cebd35 100644 --- a/dlls/d3d11/shader.c +++ b/dlls/d3d11/shader.c @@ -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); diff --git a/dlls/d3d11/utils.c b/dlls/d3d11/utils.c index 25e22f94cb7..7b08d139878 100644 --- a/dlls/d3d11/utils.c +++ b/dlls/d3d11/utils.c @@ -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;