[Mesa-dev] [PATCH] mesa: add bounds checking to eliminate buffer overrun

Courtney Goeltzenleuchter courtney at lunarg.com
Mon Apr 7 21:20:54 PDT 2014


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 explanatory comments
v3: add bugzilla reference
v4: Correct cc syntax in commit log

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74988
Cc: "9.2 10.0 10.1" <mesa-stable at lists.freedesktop.org>
---
 src/mesa/main/texcompress_etc.c | 49 +++++++++++++++++++++--------------------
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/src/mesa/main/texcompress_etc.c b/src/mesa/main/texcompress_etc.c
index cbda689..39775e2 100644
--- a/src/mesa/main/texcompress_etc.c
+++ b/src/mesa/main/texcompress_etc.c
@@ -683,9 +683,10 @@ etc2_unpack_rgb8(uint8_t *dst_row,
          etc2_rgb8_parse_block(&block, src,
                                false /* punchthrough_alpha */);
 
-         for (j = 0; j < bh; j++) {
+         /* be sure to stay within the bounds of the texture */
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_rgb8_fetch_texel(&block, i, j, dst,
                                      false /* punchthrough_alpha */);
                dst[3] = 255;
@@ -720,9 +721,9 @@ etc2_unpack_srgb8(uint8_t *dst_row,
          etc2_rgb8_parse_block(&block, src,
                                false /* punchthrough_alpha */);
 
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_rgb8_fetch_texel(&block, i, j, dst,
                                      false /* punchthrough_alpha */);
                /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
@@ -763,9 +764,9 @@ etc2_unpack_rgba8(uint8_t *dst_row,
       for (x = 0; x < width; x+= bw) {
          etc2_rgba8_parse_block(&block, src);
 
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_rgba8_fetch_texel(&block, i, j, dst);
                dst += comps;
             }
@@ -800,9 +801,9 @@ etc2_unpack_srgb8_alpha8(uint8_t *dst_row,
       for (x = 0; x < width; x+= bw) {
          etc2_rgba8_parse_block(&block, src);
 
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_rgba8_fetch_texel(&block, i, j, dst);
 
                /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
@@ -842,9 +843,9 @@ etc2_unpack_r11(uint8_t *dst_row,
       for (x = 0; x < width; x+= bw) {
          etc2_r11_parse_block(&block, src);
 
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_r11_fetch_texel(&block, i, j, dst);
                dst += comps * comp_size;
             }
@@ -878,10 +879,10 @@ etc2_unpack_rg11(uint8_t *dst_row,
          /* red component */
          etc2_r11_parse_block(&block, src);
 
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride +
                            x * comps * comp_size;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_r11_fetch_texel(&block, i, j, dst);
                dst += comps * comp_size;
             }
@@ -889,10 +890,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 < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride +
                            x * comps * comp_size;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_r11_fetch_texel(&block, i, j, dst + comp_size);
                dst += comps * comp_size;
             }
@@ -925,10 +926,10 @@ etc2_unpack_signed_r11(uint8_t *dst_row,
       for (x = 0; x < width; x+= bw) {
          etc2_r11_parse_block(&block, src);
 
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride +
                            x * comps * comp_size;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_signed_r11_fetch_texel(&block, i, j, dst);
                dst += comps * comp_size;
             }
@@ -962,10 +963,10 @@ etc2_unpack_signed_rg11(uint8_t *dst_row,
          /* red component */
          etc2_r11_parse_block(&block, src);
 
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride +
                           x * comps * comp_size;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_signed_r11_fetch_texel(&block, i, j, dst);
                dst += comps * comp_size;
             }
@@ -973,10 +974,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 < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride +
                            x * comps * comp_size;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_signed_r11_fetch_texel(&block, i, j, dst + comp_size);
                dst += comps * comp_size;
             }
@@ -1006,9 +1007,9 @@ etc2_unpack_rgb8_punchthrough_alpha1(uint8_t *dst_row,
       for (x = 0; x < width; x+= bw) {
          etc2_rgb8_parse_block(&block, src,
                                true /* punchthrough_alpha */);
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_rgb8_fetch_texel(&block, i, j, dst,
                                      true /* punchthrough_alpha */);
                dst += comps;
@@ -1041,9 +1042,9 @@ etc2_unpack_srgb8_punchthrough_alpha1(uint8_t *dst_row,
       for (x = 0; x < width; x+= bw) {
          etc2_rgb8_parse_block(&block, src,
                                true /* punchthrough_alpha */);
-         for (j = 0; j < bh; j++) {
+         for (j = 0; j < bh && (j+y) < height; j++) {
             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
-            for (i = 0; i < bw; i++) {
+            for (i = 0; i < bw && (i+x) < width; i++) {
                etc2_rgb8_fetch_texel(&block, i, j, dst,
                                      true /* punchthrough_alpha */);
                /* Convert to MESA_FORMAT_B8G8R8A8_SRGB */
-- 
1.8.3.2



More information about the mesa-dev mailing list