mesa: add bounds checking to eliminate buffer overrun

Decompressing ETC2 textures was causing intermitent segfault
by copying resulting 4x4 texel block to the destination texture
regardless of the size of the destination texture. Issue found
via application crash in GLBenchmark 3.0's Manhattan test.

v2: add more detail comment. Compute limit outside inner loops.
v3: add bugzilla reference
v4: Correct cc syntax in commit log
v5: really grab the right patch

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74988
Cc: "9.2 10.0 10.1" <mesa-stable@lists.freedesktop.org>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> [v1, suggested v2-3]
(cherry picked from commit cb4ad13685)
This commit is contained in:
Courtney Goeltzenleuchter 2014-04-08 09:10:09 -06:00 committed by Carl Worth
parent 7b580a567f
commit cbaaf8fe42

View file

@ -679,14 +679,25 @@ etc2_unpack_rgb8(uint8_t *dst_row,
for (y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
/*
* Destination texture may not be a multiple of four texels in
* height. Compute a safe height to avoid writing outside the texture.
*/
const unsigned h = MIN2(bh, height - y);
for (x = 0; x < width; x+= bw) {
etc2_rgb8_parse_block(&block, src,
false /* punchthrough_alpha */);
for (j = 0; j < bh; j++) {
/*
* Destination texture may not be a multiple of four texels in
* width. Compute a safe width to avoid writing outside the texture.
*/
const unsigned w = MIN2(bw, width - x);
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_rgb8_fetch_texel(&block, i, j, dst,
false /* punchthrough_alpha */);
dst[3] = 255;
@ -716,14 +727,17 @@ etc2_unpack_srgb8(uint8_t *dst_row,
for (y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
const unsigned h = MIN2(bh, height - y);
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
etc2_rgb8_parse_block(&block, src,
false /* punchthrough_alpha */);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_rgb8_fetch_texel(&block, i, j, dst,
false /* punchthrough_alpha */);
/* Convert to MESA_FORMAT_SARGB8 */
@ -760,13 +774,15 @@ etc2_unpack_rgba8(uint8_t *dst_row,
for (y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
const unsigned h = MIN2(bh, height - y);
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
etc2_rgba8_parse_block(&block, src);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_rgba8_fetch_texel(&block, i, j, dst);
dst += comps;
}
@ -796,14 +812,16 @@ etc2_unpack_srgb8_alpha8(uint8_t *dst_row,
uint8_t tmp;
for (y = 0; y < height; y += bh) {
const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
etc2_rgba8_parse_block(&block, src);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_rgba8_fetch_texel(&block, i, j, dst);
/* Convert to MESA_FORMAT_SARGB8 */
@ -838,14 +856,16 @@ etc2_unpack_r11(uint8_t *dst_row,
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
etc2_r11_parse_block(&block, src);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_r11_fetch_texel(&block, i, j, dst);
dst += comps * comp_size;
}
@ -873,16 +893,18 @@ etc2_unpack_rg11(uint8_t *dst_row,
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
/* red component */
etc2_r11_parse_block(&block, src);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_r11_fetch_texel(&block, i, j, dst);
dst += comps * comp_size;
}
@ -890,10 +912,10 @@ etc2_unpack_rg11(uint8_t *dst_row,
/* green component */
etc2_r11_parse_block(&block, src + 8);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_r11_fetch_texel(&block, i, j, dst + comp_size);
dst += comps * comp_size;
}
@ -921,15 +943,17 @@ etc2_unpack_signed_r11(uint8_t *dst_row,
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
etc2_r11_parse_block(&block, src);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_signed_r11_fetch_texel(&block, i, j, dst);
dst += comps * comp_size;
}
@ -957,16 +981,18 @@ etc2_unpack_signed_rg11(uint8_t *dst_row,
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
/* red component */
etc2_r11_parse_block(&block, src);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_signed_r11_fetch_texel(&block, i, j, dst);
dst += comps * comp_size;
}
@ -974,10 +1000,10 @@ etc2_unpack_signed_rg11(uint8_t *dst_row,
/* green component */
etc2_r11_parse_block(&block, src + 8);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride +
x * comps * comp_size;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_signed_r11_fetch_texel(&block, i, j, dst + comp_size);
dst += comps * comp_size;
}
@ -1002,14 +1028,16 @@ etc2_unpack_rgb8_punchthrough_alpha1(uint8_t *dst_row,
unsigned x, y, i, j;
for (y = 0; y < height; y += bh) {
const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
etc2_rgb8_parse_block(&block, src,
true /* punchthrough_alpha */);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_rgb8_fetch_texel(&block, i, j, dst,
true /* punchthrough_alpha */);
dst += comps;
@ -1037,14 +1065,16 @@ etc2_unpack_srgb8_punchthrough_alpha1(uint8_t *dst_row,
uint8_t tmp;
for (y = 0; y < height; y += bh) {
const unsigned h = MIN2(bh, height - y);
const uint8_t *src = src_row;
for (x = 0; x < width; x+= bw) {
const unsigned w = MIN2(bw, width - x);
etc2_rgb8_parse_block(&block, src,
true /* punchthrough_alpha */);
for (j = 0; j < bh; j++) {
for (j = 0; j < h; j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
for (i = 0; i < bw; i++) {
for (i = 0; i < w; i++) {
etc2_rgb8_fetch_texel(&block, i, j, dst,
true /* punchthrough_alpha */);
/* Convert to MESA_FORMAT_SARGB8 */