[Mesa-dev] [PATCH] vbo: fix possible use-after-free segfault after a VAO is deleted

Brian Paul brianp at vmware.com
Wed Apr 24 08:49:01 PDT 2013


On 04/23/2013 06:21 PM, Marek Olšák wrote:
> This like the fifth attempt to fix the issue.
>
> Also with the new "validating" flag, we can set recalculate_inputs to FALSE
> earlier in vbo_bind_arrays, because _mesa_update_state won't change it.
>
> NOTE: This is a candidate for the stable branches.
> ---
>   src/mesa/vbo/vbo_exec.c       |   20 ++++++++++++++++++--
>   src/mesa/vbo/vbo_exec.h       |    1 +
>   src/mesa/vbo/vbo_exec_array.c |    8 ++++++--
>   3 files changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/src/mesa/vbo/vbo_exec.c b/src/mesa/vbo/vbo_exec.c
> index 5827f90..fd3a052 100644
> --- a/src/mesa/vbo/vbo_exec.c
> +++ b/src/mesa/vbo/vbo_exec.c
> @@ -79,10 +79,26 @@ void vbo_exec_destroy( struct gl_context *ctx )
>    */
>   void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state )
>   {
> -   struct vbo_exec_context *exec =&vbo_context(ctx)->exec;
> +   struct vbo_context *vbo = vbo_context(ctx);
> +   struct vbo_exec_context *exec =&vbo->exec;
>
> -   if (new_state&  (_NEW_PROGRAM|_NEW_ARRAY)) {
> +   if (!exec->validating&&  new_state&  (_NEW_PROGRAM|_NEW_ARRAY)) {
>         exec->array.recalculate_inputs = GL_TRUE;
> +
> +      /* If we ended up here because a VAO was deleted, the _DrawArrays
> +       * pointer which pointed to the VAO might be invalid now, so set it
> +       * to NULL.  This prevents crashes in driver functions like Clear
> +       * where driver state validation might occur, but the vbo module is
> +       * still in an invalid state.
> +       *
> +       * Drivers should skip vertex array state validation if _DrawArrays
> +       * is NULL.  It also has no affect on performance, because attrib
> +       * bindings will be recalculated anyway.
> +       */
> +      if (vbo->last_draw_method == DRAW_ARRAYS) {
> +         ctx->Array._DrawArrays = NULL;
> +         vbo->last_draw_method = DRAW_NONE;
> +      }
>      }
>
>      if (new_state&  _NEW_EVAL)
> diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h
> index 9fc8791..bd3ab3b 100644
> --- a/src/mesa/vbo/vbo_exec.h
> +++ b/src/mesa/vbo/vbo_exec.h
> @@ -81,6 +81,7 @@ struct vbo_exec_context
>      struct gl_context *ctx;
>      GLvertexformat vtxfmt;
>      GLvertexformat vtxfmt_noop;
> +   GLboolean validating; /**<  if we're in the middle of state validation */
>
>      struct {
>         struct gl_buffer_object *bufferobj;
> diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
> index 7e61f7b..1bf3af4 100644
> --- a/src/mesa/vbo/vbo_exec_array.c
> +++ b/src/mesa/vbo/vbo_exec_array.c
> @@ -501,6 +501,7 @@ vbo_bind_arrays(struct gl_context *ctx)
>
>      if (exec->array.recalculate_inputs) {
>         recalculate_input_bindings(ctx);
> +      exec->array.recalculate_inputs = GL_FALSE;
>
>         /* Again... because we may have changed the bitmask of per-vertex varying
>          * attributes.  If we regenerate the fixed-function vertex program now
> @@ -508,10 +509,13 @@ vbo_bind_arrays(struct gl_context *ctx)
>          * need in the shader.
>          */
>         if (ctx->NewState) {
> +         /* Setting "validating" to TRUE prevents _mesa_update_state from
> +          * invalidating what we just did.
> +          */
> +         exec->validating = GL_TRUE;
>            _mesa_update_state(ctx);
> +         exec->validating = GL_FALSE;
>         }
> -
> -      exec->array.recalculate_inputs = GL_FALSE;
>      }
>   }
>

The VBO code is pretty hairy stuff (I've been digging in it too) but 
this looks OK, AFAICT.

Reviewed-by: Brian Paul <brianp at vmware.com>



More information about the mesa-dev mailing list