From df6540edf0266225489fffcc5afec4752efcd9f8 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 8 Mar 2017 10:53:05 +0100 Subject: [PATCH] wined3d: Abort on invalid instructions in shader_generate_main(). Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/arb_program_shader.c | 6 ++++-- dlls/wined3d/glsl_shader.c | 25 ++++++++++++------------- dlls/wined3d/shader.c | 8 +++++--- dlls/wined3d/wined3d_private.h | 2 +- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index ff868f95bb2..150342b07bb 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -3809,7 +3809,8 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader, } /* Base Shader Body */ - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; if(args->super.srgb_correction) { arbfp_add_sRGB_correction(buffer, fragcolor, srgbtmp[0], srgbtmp[1], srgbtmp[2], srgbtmp[3], @@ -4222,7 +4223,8 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader, /* The shader starts with the main function */ priv_ctx.in_main_func = TRUE; /* Base Shader Body */ - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return -1; if (!priv_ctx.footer_written) vshader_add_footer(&priv_ctx, shader_data, args, reg_maps, gl_info, buffer); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index d021f010251..e43a78b3355 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -6757,9 +6757,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context const struct wined3d_gl_info *gl_info = context->gl_info; struct shader_glsl_ctx_priv priv_ctx; BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]; - - /* Create the hw GLSL shader object and assign it as the shader->prgId */ - GLuint shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); + GLuint shader_id; memset(&priv_ctx, 0, sizeof(priv_ctx)); priv_ctx.cur_ps_args = args; @@ -6850,7 +6848,8 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context shader_glsl_input_pack(shader, buffer, &shader->input_signature, reg_maps, args, gl_info); /* Base Shader Body */ - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ if (reg_maps->shader_version.major < 4) @@ -6858,6 +6857,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context shader_addline(buffer, "}\n"); + shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); TRACE("Compiling shader object %u.\n", shader_id); shader_glsl_compile(gl_info, shader_id, buffer->buffer); @@ -6916,9 +6916,7 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context struct wined3d_string_buffer *buffer = &priv->shader_buffer; const struct wined3d_gl_info *gl_info = context->gl_info; struct shader_glsl_ctx_priv priv_ctx; - - /* Create the hw GLSL shader program and assign it as the shader->prgId */ - GLuint shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); + GLuint shader_id; shader_glsl_add_version_declaration(buffer, gl_info, ®_maps->shader_version); @@ -6949,7 +6947,8 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context shader_addline(buffer, "void main()\n{\n"); /* Base Shader Body */ - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ if (reg_maps->shader_version.major < 4) @@ -6957,6 +6956,7 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context shader_addline(buffer, "}\n"); + shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); TRACE("Compiling shader object %u.\n", shader_id); shader_glsl_compile(gl_info, shader_id, buffer->buffer); @@ -6974,8 +6974,6 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context struct shader_glsl_ctx_priv priv_ctx; GLuint shader_id; - shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER)); - shader_glsl_add_version_declaration(buffer, gl_info, ®_maps->shader_version); shader_glsl_enable_extensions(buffer, gl_info); @@ -6989,9 +6987,11 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context shader_addline(buffer, "uniform vec4 pos_fixup;\n"); shader_glsl_generate_sm4_rasterizer_input_setup(priv, shader, args->ps_input_count, gl_info); shader_addline(buffer, "void main()\n{\n"); - shader_generate_main(shader, buffer, reg_maps, &priv_ctx); + if (FAILED(shader_generate_main(shader, buffer, reg_maps, &priv_ctx))) + return 0; shader_addline(buffer, "}\n"); + shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER)); TRACE("Compiling shader object %u.\n", shader_id); shader_glsl_compile(gl_info, shader_id, buffer->buffer); @@ -7033,8 +7033,6 @@ static GLuint shader_glsl_generate_compute_shader(const struct wined3d_context * GLuint shader_id; unsigned int i; - shader_id = GL_EXTCALL(glCreateShader(GL_COMPUTE_SHADER)); - shader_glsl_add_version_declaration(buffer, gl_info, ®_maps->shader_version); shader_glsl_enable_extensions(buffer, gl_info); @@ -7058,6 +7056,7 @@ static GLuint shader_glsl_generate_compute_shader(const struct wined3d_context * shader_generate_main(shader, buffer, reg_maps, &priv_ctx); shader_addline(buffer, "}\n"); + shader_id = GL_EXTCALL(glCreateShader(GL_COMPUTE_SHADER)); TRACE("Compiling shader object %u.\n", shader_id); shader_glsl_compile(gl_info, shader_id, buffer->buffer); diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 7186fdfdb43..0c617c46aa2 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -2282,7 +2282,7 @@ static void shader_dump_src_param(struct wined3d_string_buffer *buffer, /* Shared code in order to generate the bulk of the shader string. * NOTE: A description of how to parse tokens can be found on MSDN. */ -void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, +HRESULT shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps, void *backend_ctx) { struct wined3d_device *device = shader->device; @@ -2320,8 +2320,8 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_st /* Unknown opcode and its parameters. */ if (ins.handler_idx == WINED3DSIH_TABLE_SIZE) { - TRACE("Skipping unrecognized instruction.\n"); - continue; + WARN("Encountered unrecognised or invalid instruction.\n"); + return WINED3DERR_INVALIDCALL; } if (ins.predicate) @@ -2330,6 +2330,8 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_st /* Call appropriate function for output target */ device->shader_backend->shader_handle_instruction(&ins); } + + return WINED3D_OK; } static void shader_dump_ins_modifiers(struct wined3d_string_buffer *buffer, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index e8c858e2dcb..8d5eee5f09b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3679,7 +3679,7 @@ BOOL string_buffer_init(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN; void string_buffer_free(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN; unsigned int shader_find_free_input_register(const struct wined3d_shader_reg_maps *reg_maps, unsigned int max) DECLSPEC_HIDDEN; -void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, +HRESULT shader_generate_main(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps, void *backend_ctx) DECLSPEC_HIDDEN; BOOL shader_match_semantic(const char *semantic_name, enum wined3d_decl_usage usage) DECLSPEC_HIDDEN;