summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Hähnle <nicolai.haehnle@amd.com>2016-04-28 15:11:42 -0500
committerNicolai Hähnle <nicolai.haehnle@amd.com>2016-04-29 11:55:06 -0500
commitaa6f88f891d6e070ea8fa251493e3d8ab2af98aa (patch)
treec7be281a6f4c4a1584b74c8dad3dc67b9c47f728
parent98c348d26b28a662d093543ecb7ca839e7883e8e (diff)
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" <mesa-stable@lists.freedesktop.org> Reviewed-by: Marek Olšák <marek.olsak@amd.com>
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c3
-rw-r--r--src/gallium/drivers/radeon/r600_streamout.c13
2 files changed, 9 insertions, 7 deletions
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 5317de0cba..cac240e8fb 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 fc9ec4859f..a001700ea1 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;