Henri Verbeet : wined3d: Validate the SM4 token count (AFL).

Alexandre Julliard julliard at winehq.org
Tue Feb 21 16:56:12 CST 2017


Module: wine
Branch: master
Commit: 7840485ac21f6eea26e9c29f5f14322ab9214985
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7840485ac21f6eea26e9c29f5f14322ab9214985

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Tue Feb 21 00:40:04 2017 +0100

wined3d: Validate the SM4 token count (AFL).

Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3d11/shader.c            |  3 +++
 dlls/d3d8/shader.c             |  2 ++
 dlls/d3d9/shader.c             |  2 ++
 dlls/wined3d/shader.c          | 10 +++++-----
 dlls/wined3d/shader_sm1.c      |  3 ++-
 dlls/wined3d/shader_sm4.c      | 15 ++++++++++++++-
 dlls/wined3d/wined3d_private.h |  3 ++-
 include/wine/wined3d.h         |  1 +
 8 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/dlls/d3d11/shader.c b/dlls/d3d11/shader.c
index 99af31b..0e0c607 100644
--- a/dlls/d3d11/shader.c
+++ b/dlls/d3d11/shader.c
@@ -76,6 +76,7 @@ static HRESULT shdr_handler(const char *data, DWORD data_size, DWORD tag, void *
             if (desc->byte_code)
                 FIXME("Multiple shader code chunks.\n");
             desc->byte_code = (const DWORD *)data;
+            desc->byte_code_size = data_size;
             break;
 
         case TAG_AON9:
@@ -103,6 +104,7 @@ static HRESULT shdr_handler(const char *data, DWORD data_size, DWORD tag, void *
                 if (desc->byte_code)
                     FIXME("Multiple shader code chunks.\n");
                 desc->byte_code = (const DWORD *)byte_code;
+                desc->byte_code_size = data_size - header->byte_code_offset;
                 TRACE("Feature level 9 shader version 0%08x, 0%08x.\n", header->shader_version, *desc->byte_code);
             }
             else
@@ -126,6 +128,7 @@ static HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length, st
     HRESULT hr;
 
     desc->byte_code = NULL;
+    desc->byte_code_size = 0;
     memset(&desc->input_signature, 0, sizeof(desc->input_signature));
     memset(&desc->output_signature, 0, sizeof(desc->output_signature));
 
diff --git a/dlls/d3d8/shader.c b/dlls/d3d8/shader.c
index f920fed..3d6ffa8 100644
--- a/dlls/d3d8/shader.c
+++ b/dlls/d3d8/shader.c
@@ -117,6 +117,7 @@ HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_d
             FIXME("Usage %#x not implemented.\n", usage);
 
         desc.byte_code = byte_code;
+        desc.byte_code_size = ~(size_t)0;
         desc.input_signature.element_count = 0;
         desc.output_signature.element_count = 0;
         desc.max_version = 1;
@@ -166,6 +167,7 @@ HRESULT d3d8_pixel_shader_init(struct d3d8_pixel_shader *shader, struct d3d8_dev
     shader->handle = shader_handle;
 
     desc.byte_code = byte_code;
+    desc.byte_code_size = ~(size_t)0;
     desc.input_signature.element_count = 0;
     desc.output_signature.element_count = 0;
     desc.max_version = 1;
diff --git a/dlls/d3d9/shader.c b/dlls/d3d9/shader.c
index b66762d..9bb8642 100644
--- a/dlls/d3d9/shader.c
+++ b/dlls/d3d9/shader.c
@@ -143,6 +143,7 @@ HRESULT vertexshader_init(struct d3d9_vertexshader *shader, struct d3d9_device *
     shader->IDirect3DVertexShader9_iface.lpVtbl = &d3d9_vertexshader_vtbl;
 
     desc.byte_code = byte_code;
+    desc.byte_code_size = ~(size_t)0;
     desc.input_signature.element_count = 0;
     desc.output_signature.element_count = 0;
     desc.max_version = 3;
@@ -294,6 +295,7 @@ HRESULT pixelshader_init(struct d3d9_pixelshader *shader, struct d3d9_device *de
     shader->IDirect3DPixelShader9_iface.lpVtbl = &d3d9_pixelshader_vtbl;
 
     desc.byte_code = byte_code;
+    desc.byte_code_size = ~(size_t)0;
     desc.input_signature.element_count = 0;
     desc.output_signature.element_count = 0;
     desc.max_version = 3;
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 9688b30..181cebd 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -2854,7 +2854,7 @@ const struct wined3d_shader_backend_ops none_shader_backend =
 };
 
 static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *byte_code,
-        DWORD float_const_count, enum wined3d_shader_type type, unsigned int max_version)
+        size_t byte_code_size, DWORD float_const_count, enum wined3d_shader_type type, unsigned int max_version)
 {
     struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     const struct wined3d_shader_frontend *fe;
@@ -2862,8 +2862,8 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
     unsigned int backend_version;
     const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
 
-    TRACE("shader %p, byte_code %p, float_const_count %u, type %#x, max_version %u.\n",
-            shader, byte_code, float_const_count, type, max_version);
+    TRACE("shader %p, byte_code %p, byte_code_size %#lx, float_const_count %u, type %#x, max_version %u.\n",
+            shader, byte_code, (long)byte_code_size, float_const_count, type, max_version);
 
     list_init(&shader->constantsF);
     list_init(&shader->constantsB);
@@ -2878,7 +2878,7 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
         return WINED3DERR_INVALIDCALL;
     }
     shader->frontend = fe;
-    shader->frontend_data = fe->shader_init(byte_code, &shader->output_signature);
+    shader->frontend_data = fe->shader_init(byte_code, byte_code_size, &shader->output_signature);
     if (!shader->frontend_data)
     {
         FIXME("Failed to initialize frontend.\n");
@@ -3193,7 +3193,7 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
     list_add_head(&device->shaders, &shader->shader_list_entry);
 
     if (FAILED(hr = shader_set_function(shader, desc->byte_code,
-            float_const_count, type, desc->max_version)))
+            desc->byte_code_size, float_const_count, type, desc->max_version)))
     {
         WARN("Failed to set function, hr %#x.\n", hr);
         shader_cleanup(shader);
diff --git a/dlls/wined3d/shader_sm1.c b/dlls/wined3d/shader_sm1.c
index 2437608..40c9e79 100644
--- a/dlls/wined3d/shader_sm1.c
+++ b/dlls/wined3d/shader_sm1.c
@@ -533,7 +533,8 @@ static unsigned int shader_skip_unrecognized(const struct wined3d_sm1_data *priv
     return tokens_read;
 }
 
-static void *shader_sm1_init(const DWORD *byte_code, const struct wined3d_shader_signature *output_signature)
+static void *shader_sm1_init(const DWORD *byte_code, size_t byte_code_size,
+        const struct wined3d_shader_signature *output_signature)
 {
     struct wined3d_sm1_data *priv;
     BYTE major, minor;
diff --git a/dlls/wined3d/shader_sm4.c b/dlls/wined3d/shader_sm4.c
index a9d731f..baffe2d 100644
--- a/dlls/wined3d/shader_sm4.c
+++ b/dlls/wined3d/shader_sm4.c
@@ -1121,17 +1121,30 @@ static enum wined3d_data_type map_data_type(char t)
     }
 }
 
-static void *shader_sm4_init(const DWORD *byte_code, const struct wined3d_shader_signature *output_signature)
+static void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
+        const struct wined3d_shader_signature *output_signature)
 {
     DWORD version_token, token_count;
     struct wined3d_sm4_data *priv;
     unsigned int i;
 
+    if (byte_code_size / sizeof(*byte_code) < 2)
+    {
+        WARN("Invalid byte code size %lu.\n", (long)byte_code_size);
+        return NULL;
+    }
+
     version_token = byte_code[0];
     TRACE("Version: 0x%08x.\n", version_token);
     token_count = byte_code[1];
     TRACE("Token count: %u.\n", token_count);
 
+    if (token_count < 2 || byte_code_size / sizeof(*byte_code) < token_count)
+    {
+        WARN("Invalid token count %u.\n", token_count);
+        return NULL;
+    }
+
     if (!(priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv))))
     {
         ERR("Failed to allocate private data\n");
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d4380a5..485bc38 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1083,7 +1083,8 @@ struct wined3d_shader_loop_control
 
 struct wined3d_shader_frontend
 {
-    void *(*shader_init)(const DWORD *ptr, const struct wined3d_shader_signature *output_signature);
+    void *(*shader_init)(const DWORD *byte_code, size_t byte_code_size,
+            const struct wined3d_shader_signature *output_signature);
     void (*shader_free)(void *data);
     void (*shader_read_header)(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version);
     void (*shader_read_instruction)(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins);
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index e216520..834cf11 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -1959,6 +1959,7 @@ struct wined3d_shader_signature
 struct wined3d_shader_desc
 {
     const DWORD *byte_code;
+    size_t byte_code_size;
     struct wined3d_shader_signature input_signature;
     struct wined3d_shader_signature output_signature;
     unsigned int max_version;




More information about the wine-cvs mailing list