From fd2fbc558b8e9c6ffdfbd90473e5b77e20f771e7 Mon Sep 17 00:00:00 2001 From: Vadym Shovkoplias Date: Tue, 11 Jan 2022 10:21:05 +0200 Subject: [PATCH] glthread: Check out of bounds for MultiDrawElementsBaseVertex cmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure draw count is not high so the MultiDrawElementsBaseVertex cmd can fit the queue buffer. v2: add the same check for _mesa_marshal_MultiDrawArrays and add additional assert to _mesa_glthread_allocate_command (Pierre-Eric) Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5719 Signed-off-by: Vadym Shovkoplias Reviewed-by: Marek Olšák Reviewed-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/mesa/main/glthread_draw.c | 28 +++++++++++++++++++++------- src/mesa/main/glthread_marshal.h | 2 ++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/mesa/main/glthread_draw.c b/src/mesa/main/glthread_draw.c index 7a0c72a6ff8..21fce5010ef 100644 --- a/src/mesa/main/glthread_draw.c +++ b/src/mesa/main/glthread_draw.c @@ -459,7 +459,7 @@ _mesa_unmarshal_MultiDrawArrays(struct gl_context *ctx, return cmd->cmd_base.cmd_size; } -static ALWAYS_INLINE void +static ALWAYS_INLINE bool multi_draw_arrays_async(struct gl_context *ctx, GLenum mode, const GLint *first, const GLsizei *count, GLsizei draw_count, unsigned user_buffer_mask, @@ -472,6 +472,11 @@ multi_draw_arrays_async(struct gl_context *ctx, GLenum mode, first_size + count_size + buffers_size; struct marshal_cmd_MultiDrawArrays *cmd; + /* Make sure cmd can fit the queue buffer */ + if (cmd_size > MARSHAL_MAX_CMD_SIZE) { + return false; + } + cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawArrays, cmd_size); cmd->mode = mode; @@ -487,6 +492,8 @@ multi_draw_arrays_async(struct gl_context *ctx, GLenum mode, variable_data += count_size; memcpy(variable_data, buffers, buffers_size); } + + return true; } void GLAPIENTRY @@ -502,8 +509,8 @@ _mesa_marshal_MultiDrawArrays(GLenum mode, const GLint *first, goto sync; if (draw_count >= 0 && - (ctx->API == API_OPENGL_CORE || !user_buffer_mask)) { - multi_draw_arrays_async(ctx, mode, first, count, draw_count, 0, NULL); + (ctx->API == API_OPENGL_CORE || !user_buffer_mask) && + multi_draw_arrays_async(ctx, mode, first, count, draw_count, 0, NULL)) { return; } @@ -938,7 +945,7 @@ _mesa_unmarshal_MultiDrawElementsBaseVertex(struct gl_context *ctx, return cmd->cmd_base.cmd_size; } -static ALWAYS_INLINE void +static ALWAYS_INLINE bool multi_draw_elements_async(struct gl_context *ctx, GLenum mode, const GLsizei *count, GLenum type, const GLvoid *const *indices, GLsizei draw_count, @@ -955,6 +962,11 @@ multi_draw_elements_async(struct gl_context *ctx, GLenum mode, count_size + indices_size + basevertex_size + buffers_size; struct marshal_cmd_MultiDrawElementsBaseVertex *cmd; + /* Make sure cmd can fit the queue buffer */ + if (cmd_size > MARSHAL_MAX_CMD_SIZE) { + return false; + } + cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawElementsBaseVertex, cmd_size); cmd->mode = mode; cmd->type = type; @@ -976,6 +988,8 @@ multi_draw_elements_async(struct gl_context *ctx, GLenum mode, if (user_buffer_mask) memcpy(variable_data, buffers, buffers_size); + + return true; } void GLAPIENTRY @@ -999,9 +1013,9 @@ _mesa_marshal_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, (ctx->API == API_OPENGL_CORE || !is_index_type_valid(type) || (!user_buffer_mask && !has_user_indices))) { - multi_draw_elements_async(ctx, mode, count, type, indices, draw_count, - basevertex, NULL, 0, NULL); - return; + if (multi_draw_elements_async(ctx, mode, count, type, indices, + draw_count, basevertex, NULL, 0, NULL)) + return; } bool need_index_bounds = user_buffer_mask & ~vao->NonZeroDivisorMask; diff --git a/src/mesa/main/glthread_marshal.h b/src/mesa/main/glthread_marshal.h index 67fa1e0e097..aac940dc08c 100644 --- a/src/mesa/main/glthread_marshal.h +++ b/src/mesa/main/glthread_marshal.h @@ -59,6 +59,8 @@ _mesa_glthread_allocate_command(struct gl_context *ctx, struct glthread_state *glthread = &ctx->GLThread; const unsigned num_elements = align(size, 8) / 8; + assert (num_elements <= MARSHAL_MAX_CMD_SIZE / 8); + if (unlikely(glthread->used + num_elements > MARSHAL_MAX_CMD_SIZE / 8)) _mesa_glthread_flush_batch(ctx);