[PATCH 2/6] wined3d: Validate the SM4 token count (AFL).
Henri Verbeet
hverbeet at codeweavers.com
Mon Feb 20 17:40:04 CST 2017
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
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;
--
2.1.4
More information about the wine-patches
mailing list