[PATCH 4/5] d3d10: Validate offsets and sizes in shader_parse_signature() (AFL).

Henri Verbeet hverbeet at codeweavers.com
Tue May 24 12:46:44 CDT 2016


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/d3d10/d3d10_private.h |  4 ++--
 dlls/d3d10/effect.c        | 38 +++++++++++++++++++++++++++++++++++++-
 dlls/d3d10/utils.c         |  4 ++--
 3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/dlls/d3d10/d3d10_private.h b/dlls/d3d10/d3d10_private.h
index 0e27dfe..dc41224 100644
--- a/dlls/d3d10/d3d10_private.h
+++ b/dlls/d3d10/d3d10_private.h
@@ -294,9 +294,9 @@ static inline void write_dword(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 *location, const char **ptr, unsigned int count) DECLSPEC_HIDDEN;
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c
index c7eed1a..df35640 100644
--- a/dlls/d3d10/effect.c
+++ b/dlls/d3d10/effect.c
@@ -267,6 +267,25 @@ static BOOL copy_name(const char *ptr, char **name)
     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)
 {
     D3D10_SIGNATURE_PARAMETER_DESC *e;
@@ -274,11 +293,23 @@ static HRESULT shader_parse_signature(const char *data, DWORD data_size, struct
     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("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));
     if (!e)
     {
@@ -292,7 +323,12 @@ static HRESULT shader_parse_signature(const char *data, DWORD data_size, struct
         UINT mask;
 
         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].SystemValueType);
         read_dword(&ptr, &e[i].ComponentType);
diff --git a/dlls/d3d10/utils.c b/dlls/d3d10/utils.c
index 618fdee..be88d5a 100644
--- a/dlls/d3d10/utils.c
+++ b/dlls/d3d10/utils.c
@@ -217,7 +217,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;
@@ -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_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;
-- 
2.1.4




More information about the wine-patches mailing list