From 14379a0644ed69c5b7a6c6150ae91eba6f316e33 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 17 Oct 2014 13:31:53 -0600 Subject: [PATCH] glsl: fix several use-after-free bugs The get_variable_being_redeclared() function can free the 'var' argument. Thereafter, we cannot assume that 'var' is a valid pointer. This patch replaces 'var->name' with 'earlier->name' in two places and calls is_gl_identifier(var->name) before 'var' might get freed. This fixes several piglit GLSL crashes, including: spec/glsl-1.50/execution/geometry/clip-distance-in-param spec/glsl-1.50/execution/geometry/clip-distance-bulk-copy spec/glsl-1.50/compiler/gs-redeclares-pervertex-out-before-global-redeclaration.geom I'm not sure why these were not spotted sooner. A similar bug was previously fixed by f9cecca7a. Cc: Reviewed-by: Chris Forbes --- src/glsl/ast_to_hir.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index afbb3b2..fe1e129 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -3767,7 +3767,7 @@ ast_declarator_list::hir(exec_list *instructions, earlier->data.how_declared == ir_var_declared_in_block) { _mesa_glsl_error(&loc, state, "`%s' has already been redeclared using " - "gl_PerVertex", var->name); + "gl_PerVertex", earlier->name); } earlier->data.how_declared = ir_var_declared_normally; } @@ -5706,17 +5706,21 @@ ast_interface_block::hir(exec_list *instructions, var->data.stream = this->layout.stream; + /* Examine var name here since var may get deleted in the next call */ + bool var_is_gl_id = is_gl_identifier(var->name); + if (redeclaring_per_vertex) { ir_variable *earlier = get_variable_being_redeclared(var, loc, state, true /* allow_all_redeclarations */); - if (!is_gl_identifier(var->name) || earlier == NULL) { + if (!var_is_gl_id || earlier == NULL) { _mesa_glsl_error(&loc, state, "redeclaration of gl_PerVertex can only " "include built-in variables"); } else if (earlier->data.how_declared == ir_var_declared_normally) { _mesa_glsl_error(&loc, state, - "`%s' has already been redeclared", var->name); + "`%s' has already been redeclared", + earlier->name); } else { earlier->data.how_declared = ir_var_declared_in_block; earlier->reinit_interface_type(block_type); -- 2.7.4