From 8eef6ad2e2f90feac231a2e09ed4765f23ed1557 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 24 Apr 2013 01:29:26 +0200 Subject: [PATCH] vbo: fix possible use-after-free segfault after a VAO is deleted 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. v2: fixed a typo Reviewed-by: Brian Paul --- 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 0a8fbf8ede1..926e7b46ddb 100644 --- a/src/mesa/vbo/vbo_exec.c +++ b/src/mesa/vbo/vbo_exec.c @@ -80,10 +80,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 effect 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 9fc87917c59..bd3ab3ba6f3 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 7e61f7b31fd..1bf3af47b8b 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; } } -- 2.30.2