[Mesa-dev] [PATCH v2] glsl: fix heap-use-after-free in ast_declarator_list::hir()

Samuel Iglesias Gonsálvez siglesias at igalia.com
Thu Feb 9 14:20:11 UTC 2017


On Thu, 2017-02-09 at 13:34 +0100, Ian Romanick wrote:
> NAK.
> 
> The way the code is currently architected, if earlier is non-NULL,
> var
> should not be used.  There are quite a few places where the callees
> do
> things like 'const glsl_type *const t = (earlier == NULL) ? var->type 
> :
> earlier->type;'.  This is a bit confusing, but this change muddles
> that
> and makes it worse.
> 
> I think the actual use-after-free is in setting implicitly_sized at
> line
> 5265.  I think doing something like
> 
>         const enum ir_variable_mode *mode = earlier == NULL
>             ? &var->data.mode : &earlier->data.mode;
>          const bool implicitly_sized =
>             (mode == ir_var_shader_in &&
>              state->stage >= MESA_SHADER_TESS_CTRL &&
>              state->stage <= MESA_SHADER_GEOMETRY) ||
>             (mode == ir_var_shader_out &&
>              state->stage == MESA_SHADER_TESS_CTRL);
> 
> should also fix the problem.  This should be tagged for stable.
> 

Right. I'll do it.

> After that fix, we may want to look at rearchitecting this code to be
> less... confusing.  The fundamental problem is
> get_variable_being_redeclared is really trying to return two pieces
> of
> information, but it does this through a single variable.
> 
> 1. Is this actually a redeclaration?
> 
> 2. What is the variable that needs to be modified?
> 
> When get_variable_being_redeclared returns NULL, it's not a
> redeclaration, and the variable being modified is the ir_variable
> passed
> in.  When it returns non-NULL, it is a redeclaration, and the
> variable
> being modified is the one returned.
> 
> Maybe the function should always return non-NULL (returning either
> 'earlier' or 'var') and have an extra parameter 'bool
> *redeclaration'.
> I think that would result in almost no changes to the second caller
> and
> several simplifications to the first caller.  Thoughts?
> 

Yeah, that could improve things.

I am going to send two patches, one is the aforementioned fix (with Cc
to mesa-stable@) and another with the refactor.

Sam

> On 02/07/2017 01:47 PM, Samuel Iglesias Gonsálvez wrote:
> > The get_variable_being_redeclared() function can free 'var' because
> > a re-declaration of an unsized array variable can establish the
> > size, so
> > we set the array type to the 'earlier' declaration and free 'var'
> > as it is
> > not needed anymore.
> > 
> > However, the same 'var' is referenced later in
> > ast_declarator_list::hir().
> > 
> > This patch fixes it by assign the pointer 'var' to the pointer
> > 'earlier'.
> > 
> > This error was detected by Address Sanitizer.
> > 
> > v2:
> > 
> > * Pointer-to-pointer assignment (Bartosz Tomczyk)
> > 
> > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99677
> > Signed-off-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
> > ---
> > 
> > Another possibility is to use reference-to-pointer but it is a C++
> > thing. IIRC, we agreed on avoiding C++-specific features to make it
> > easy for C developers, but I have no strong opinion for either
> > option.
> > 
> >  src/compiler/glsl/ast_to_hir.cpp | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/src/compiler/glsl/ast_to_hir.cpp
> > b/src/compiler/glsl/ast_to_hir.cpp
> > index b31b61d1ed6..93ba1d510fa 100644
> > --- a/src/compiler/glsl/ast_to_hir.cpp
> > +++ b/src/compiler/glsl/ast_to_hir.cpp
> > @@ -3958,10 +3958,12 @@ apply_type_qualifier_to_variable(const
> > struct ast_type_qualifier *qual,
> >   * is a redeclaration, \c NULL otherwise.
> >   */
> >  static ir_variable *
> > -get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
> > +get_variable_being_redeclared(ir_variable **var_pointer, YYLTYPE
> > loc,
> >                                struct _mesa_glsl_parse_state
> > *state,
> >                                bool allow_all_redeclarations)
> >  {
> > +   ir_variable *var = *var_pointer;
> > +
> >     /* Check if this declaration is actually a re-declaration,
> > either to
> >      * resize an array or add qualifiers to an existing variable.
> >      *
> > @@ -3999,7 +4001,7 @@ get_variable_being_redeclared(ir_variable
> > *var, YYLTYPE loc,
> >  
> >        earlier->type = var->type;
> >        delete var;
> > -      var = NULL;
> > +      *var_pointer = earlier;
> >     } else if ((state->ARB_fragment_coord_conventions_enable ||
> >                state->is_version(150, 0))
> >                && strcmp(var->name, "gl_FragCoord") == 0
> > @@ -5207,7 +5209,7 @@ ast_declarator_list::hir(exec_list
> > *instructions,
> >        bool var_is_gl_id = is_gl_identifier(var->name);
> >  
> >        ir_variable *earlier =
> > -         get_variable_being_redeclared(var, decl->get_location(),
> > state,
> > +         get_variable_being_redeclared(&var, decl->get_location(), 
> > state,
> >                                         false /*
> > allow_all_redeclarations */);
> >        if (earlier != NULL) {
> >           if (var_is_gl_id &&
> > @@ -7873,7 +7875,7 @@ ast_interface_block::hir(exec_list
> > *instructions,
> >  
> >           if (redeclaring_per_vertex) {
> >              ir_variable *earlier =
> > -               get_variable_being_redeclared(var, loc, state,
> > +               get_variable_being_redeclared(&var, loc, state,
> >                                               true /*
> > allow_all_redeclarations */);
> >              if (!var_is_gl_id || earlier == NULL) {
> >                 _mesa_glsl_error(&loc, state,
> > 
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170209/df3e02ff/attachment-0001.sig>


More information about the mesa-dev mailing list