From: Nicolai Hähnle Date: Thu, 28 Apr 2016 20:11:42 +0000 (-0500) Subject: gallium/radeon: fix crash in r600_set_streamout_targets X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aa6f88f891d6e070ea8fa251493e3d8ab2af98aa;p=mesa.git gallium/radeon: fix crash in r600_set_streamout_targets Protect against dereferencing a gap in the targets array. This was triggered by a test in the Khronos CTS. Cc: "11.1 11.2" Reviewed-by: Marek Olšák --- diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 5317de0cbab..cac240e8fba 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -2802,7 +2802,8 @@ static void r600_invalidate_buffer(struct pipe_context *ctx, struct pipe_resourc } /* Streamout buffers. */ for (i = 0; i < rctx->b.streamout.num_targets; i++) { - if (rctx->b.streamout.targets[i]->b.buffer == &rbuffer->b.b) { + if (rctx->b.streamout.targets[i] && + rctx->b.streamout.targets[i]->b.buffer == &rbuffer->b.b) { if (rctx->b.streamout.begin_emitted) { r600_emit_streamout_end(&rctx->b); } diff --git a/src/gallium/drivers/radeon/r600_streamout.c b/src/gallium/drivers/radeon/r600_streamout.c index fc9ec4859f6..a001700ea19 100644 --- a/src/gallium/drivers/radeon/r600_streamout.c +++ b/src/gallium/drivers/radeon/r600_streamout.c @@ -116,7 +116,7 @@ void r600_set_streamout_targets(struct pipe_context *ctx, { struct r600_common_context *rctx = (struct r600_common_context *)ctx; unsigned i; - unsigned append_bitmask = 0; + unsigned enabled_mask = 0, append_bitmask = 0; /* Stop streamout. */ if (rctx->streamout.num_targets && rctx->streamout.begin_emitted) { @@ -126,18 +126,19 @@ void r600_set_streamout_targets(struct pipe_context *ctx, /* Set the new targets. */ for (i = 0; i < num_targets; i++) { pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->streamout.targets[i], targets[i]); + if (!targets[i]) + continue; + r600_context_add_resource_size(ctx, targets[i]->buffer); + enabled_mask |= 1 << i; if (offsets[i] == ((unsigned)-1)) - append_bitmask |= 1 << i; + append_bitmask |= 1 << i; } for (; i < rctx->streamout.num_targets; i++) { pipe_so_target_reference((struct pipe_stream_output_target**)&rctx->streamout.targets[i], NULL); } - rctx->streamout.enabled_mask = (num_targets >= 1 && targets[0] ? 1 : 0) | - (num_targets >= 2 && targets[1] ? 2 : 0) | - (num_targets >= 3 && targets[2] ? 4 : 0) | - (num_targets >= 4 && targets[3] ? 8 : 0); + rctx->streamout.enabled_mask = enabled_mask; rctx->streamout.num_targets = num_targets; rctx->streamout.append_bitmask = append_bitmask;