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

Marek Olšák maraeo at gmail.com
Tue Apr 23 17:21:41 PDT 2013


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;
    }
 }
 
-- 
1.7.10.4



More information about the mesa-dev mailing list