draw: Allocate extra padding for extra shader outputs.
This prevents read buffer overflows in dup_vertex(), when draw stages allocate extra shader outputs after the vertex buffers are allocated. The original issue can be exercised with upcoming piglit/tests/general/vertex-fallbacks.c test. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Cc: 21.0 21.1 <mesa-stable@lists.freedesktop.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10836>
This commit is contained in:
@@ -589,7 +589,8 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
|
|||||||
output_verts[i].stride = output_verts[i].vertex_size;
|
output_verts[i].stride = output_verts[i].vertex_size;
|
||||||
output_verts[i].verts =
|
output_verts[i].verts =
|
||||||
(struct vertex_header *)MALLOC(output_verts[i].vertex_size *
|
(struct vertex_header *)MALLOC(output_verts[i].vertex_size *
|
||||||
total_verts_per_buffer * shader->num_invocations);
|
total_verts_per_buffer * shader->num_invocations +
|
||||||
|
DRAW_EXTRA_VERTICES_PADDING);
|
||||||
debug_assert(output_verts[i].verts);
|
debug_assert(output_verts[i].verts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,8 +76,8 @@ boolean draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr )
|
|||||||
if (nr != 0)
|
if (nr != 0)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
ubyte *store = (ubyte *) MALLOC( MAX_VERTEX_SIZE * nr );
|
ubyte *store = (ubyte *) MALLOC( MAX_VERTEX_SIZE * nr +
|
||||||
|
DRAW_EXTRA_VERTICES_PADDING );
|
||||||
if (!store)
|
if (!store)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@@ -268,7 +268,7 @@ draw_prim_assembler_run(struct draw_context *draw,
|
|||||||
output_verts->vertex_size = input_verts->vertex_size;
|
output_verts->vertex_size = input_verts->vertex_size;
|
||||||
output_verts->stride = input_verts->stride;
|
output_verts->stride = input_verts->stride;
|
||||||
output_verts->verts = (struct vertex_header*)MALLOC(
|
output_verts->verts = (struct vertex_header*)MALLOC(
|
||||||
input_verts->vertex_size * max_verts);
|
input_verts->vertex_size * max_verts + DRAW_EXTRA_VERTICES_PADDING);
|
||||||
output_verts->count = 0;
|
output_verts->count = 0;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -59,6 +59,37 @@ struct gallivm_state;
|
|||||||
*/
|
*/
|
||||||
#define DRAW_MAX_FETCH_IDX 0xffffffff
|
#define DRAW_MAX_FETCH_IDX 0xffffffff
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of extra shader outputs. These are allocated by:
|
||||||
|
* - draw_pipe_aaline.c (1)
|
||||||
|
* - draw_pipe_aapoint.c (1)
|
||||||
|
* - draw_pipe_unfilled.c (1)
|
||||||
|
* - draw_pipe_wide_point.c (up to 32)
|
||||||
|
* - draw_prim_assembler.c (1)
|
||||||
|
*/
|
||||||
|
#define DRAW_MAX_EXTRA_SHADER_OUTPUTS 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Despite some efforts to determine the number of extra shader outputs ahead
|
||||||
|
* of time, the matter of fact is that this number will vary as primitives
|
||||||
|
* flow through the draw pipeline. In particular, aaline/aapoint stages
|
||||||
|
* only allocate their extra shader outputs on the first line/point.
|
||||||
|
*
|
||||||
|
* Consequently dup_vert() ends up copying vertices larger than those
|
||||||
|
* allocated.
|
||||||
|
*
|
||||||
|
* Ideally we'd keep track of incoming/outgoing vertex sizes (and strides)
|
||||||
|
* throughout the draw pipeline, but unfortunately we recompute these all over
|
||||||
|
* the place, so preemptively expanding the vertex stride/size does not work
|
||||||
|
* as mismatches ensue.
|
||||||
|
*
|
||||||
|
* As stopgap to prevent buffer read overflows, we allocate an extra bit of
|
||||||
|
* padding at the end of temporary vertex buffers, allowing dup_vert() to copy
|
||||||
|
* more vertex attributes than allocated.
|
||||||
|
*/
|
||||||
|
#define DRAW_EXTRA_VERTICES_PADDING \
|
||||||
|
(DRAW_MAX_EXTRA_SHADER_OUTPUTS * sizeof(float[4]))
|
||||||
|
|
||||||
struct pipe_context;
|
struct pipe_context;
|
||||||
struct draw_vertex_shader;
|
struct draw_vertex_shader;
|
||||||
struct draw_context;
|
struct draw_context;
|
||||||
@@ -361,9 +392,9 @@ struct draw_context
|
|||||||
*/
|
*/
|
||||||
struct {
|
struct {
|
||||||
uint num;
|
uint num;
|
||||||
uint semantic_name[10];
|
uint semantic_name[DRAW_MAX_EXTRA_SHADER_OUTPUTS];
|
||||||
uint semantic_index[10];
|
uint semantic_index[DRAW_MAX_EXTRA_SHADER_OUTPUTS];
|
||||||
uint slot[10];
|
uint slot[DRAW_MAX_EXTRA_SHADER_OUTPUTS];
|
||||||
} extra_shader_outputs;
|
} extra_shader_outputs;
|
||||||
|
|
||||||
unsigned instance_id;
|
unsigned instance_id;
|
||||||
|
@@ -214,7 +214,8 @@ draw_vertex_shader_run(struct draw_vertex_shader *vshader,
|
|||||||
output_verts->count = input_verts->count;
|
output_verts->count = input_verts->count;
|
||||||
output_verts->verts =
|
output_verts->verts =
|
||||||
(struct vertex_header *)MALLOC(output_verts->vertex_size *
|
(struct vertex_header *)MALLOC(output_verts->vertex_size *
|
||||||
align(output_verts->count, 4));
|
align(output_verts->count, 4) +
|
||||||
|
DRAW_EXTRA_VERTICES_PADDING);
|
||||||
|
|
||||||
vshader->run_linear(vshader,
|
vshader->run_linear(vshader,
|
||||||
(const float (*)[4])input_verts->verts->data,
|
(const float (*)[4])input_verts->verts->data,
|
||||||
@@ -254,7 +255,8 @@ fetch_pipeline_generic(struct draw_pt_middle_end *middle,
|
|||||||
fetched_vert_info.stride = fpme->vertex_size;
|
fetched_vert_info.stride = fpme->vertex_size;
|
||||||
fetched_vert_info.verts =
|
fetched_vert_info.verts =
|
||||||
(struct vertex_header *)MALLOC(fpme->vertex_size *
|
(struct vertex_header *)MALLOC(fpme->vertex_size *
|
||||||
align(fetch_info->count, 4));
|
align(fetch_info->count, 4) +
|
||||||
|
DRAW_EXTRA_VERTICES_PADDING);
|
||||||
if (!fetched_vert_info.verts) {
|
if (!fetched_vert_info.verts) {
|
||||||
assert(0);
|
assert(0);
|
||||||
return;
|
return;
|
||||||
|
@@ -595,7 +595,8 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle,
|
|||||||
llvm_vert_info.stride = fpme->vertex_size;
|
llvm_vert_info.stride = fpme->vertex_size;
|
||||||
llvm_vert_info.verts = (struct vertex_header *)
|
llvm_vert_info.verts = (struct vertex_header *)
|
||||||
MALLOC(fpme->vertex_size *
|
MALLOC(fpme->vertex_size *
|
||||||
align(fetch_info->count, lp_native_vector_width / 32));
|
align(fetch_info->count, lp_native_vector_width / 32) +
|
||||||
|
DRAW_EXTRA_VERTICES_PADDING);
|
||||||
if (!llvm_vert_info.verts) {
|
if (!llvm_vert_info.verts) {
|
||||||
assert(0);
|
assert(0);
|
||||||
return;
|
return;
|
||||||
|
@@ -158,7 +158,8 @@ static void PIPE_CDECL vsvg_run_elts( struct draw_vs_variant *variant,
|
|||||||
{
|
{
|
||||||
struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
|
struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
|
||||||
unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
|
unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
|
||||||
void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
|
void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride +
|
||||||
|
DRAW_EXTRA_VERTICES_PADDING );
|
||||||
|
|
||||||
if (0) debug_printf("%s %d \n", __FUNCTION__, count);
|
if (0) debug_printf("%s %d \n", __FUNCTION__, count);
|
||||||
|
|
||||||
@@ -227,7 +228,8 @@ static void PIPE_CDECL vsvg_run_linear( struct draw_vs_variant *variant,
|
|||||||
{
|
{
|
||||||
struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
|
struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
|
||||||
unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
|
unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
|
||||||
void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
|
void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride +
|
||||||
|
DRAW_EXTRA_VERTICES_PADDING );
|
||||||
|
|
||||||
if (0) debug_printf("%s %d %d (sz %d, %d)\n", __FUNCTION__, start, count,
|
if (0) debug_printf("%s %d %d (sz %d, %d)\n", __FUNCTION__, start, count,
|
||||||
vsvg->base.key.output_stride,
|
vsvg->base.key.output_stride,
|
||||||
|
Reference in New Issue
Block a user