OSDN Git Service

Fix potential segfault when trying to read pixels outside renderbuffer bounds.
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 16 Sep 2005 21:15:27 +0000 (21:15 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 16 Sep 2005 21:15:27 +0000 (21:15 +0000)
Use _swrast_get_values() which does clipping.

src/mesa/swrast/s_blend.c
src/mesa/swrast/s_depth.c
src/mesa/swrast/s_depth.h
src/mesa/swrast/s_logic.c
src/mesa/swrast/s_masking.c
src/mesa/swrast/s_span.c
src/mesa/swrast/s_span.h
src/mesa/swrast/s_stencil.c

index d34ecac..d94ff39 100644 (file)
@@ -858,8 +858,8 @@ _swrast_blend_span(GLcontext *ctx, struct gl_renderbuffer *rb,
    /* Read span of current frame buffer pixels */
    if (span->arrayMask & SPAN_XY) {
       /* array of x/y pixel coords */
-      rb->GetValues(ctx, rb, span->end, span->array->x, span->array->y,
-                    framebuffer);
+      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+                         framebuffer, 4 * sizeof(GLchan));
    }
    else {
       /* horizontal run of pixels */
index 54aa040..c70fdea 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "s_depth.h"
 #include "s_context.h"
+#include "s_span.h"
 
 
 /**
@@ -1076,14 +1077,14 @@ depth_test_pixels( GLcontext *ctx, struct sw_span *span )
       /* read depth values from buffer, test, write back */
       if (rb->DataType == GL_UNSIGNED_SHORT) {
          GLushort zbuffer[MAX_WIDTH];
-         rb->GetValues(ctx, rb, count, x, y, zbuffer);
+         _swrast_get_values(ctx, rb, count, x, y, zbuffer, sizeof(GLushort));
          depth_test_span16(ctx, count, zbuffer, z, mask );
          rb->PutValues(ctx, rb, count, x, y, zbuffer, NULL);
       }
       else {
          GLuint zbuffer[MAX_WIDTH];
          ASSERT(rb->DataType == GL_UNSIGNED_INT);
-         rb->GetValues(ctx, rb, count, x, y, zbuffer);
+         _swrast_get_values(ctx, rb, count, x, y, zbuffer, sizeof(GLuint));
          depth_test_span32(ctx, count, zbuffer, z, mask );
          rb->PutValues(ctx, rb, count, x, y, zbuffer, NULL);
       }
@@ -1130,7 +1131,8 @@ _swrast_depth_bounds_test( GLcontext *ctx, struct sw_span *span )
       /* get 16-bit values */
       GLushort zbuffer16[MAX_WIDTH], *zbuffer;
       if (span->arrayMask & SPAN_XY) {
-         rb->GetValues(ctx, rb, count, span->array->x, span->array->y, zbuffer16);
+         _swrast_get_values(ctx, rb, count, span->array->x, span->array->y,
+                            zbuffer16, sizeof(GLushort));
          zbuffer = zbuffer16;
       }
       else {
@@ -1156,7 +1158,8 @@ _swrast_depth_bounds_test( GLcontext *ctx, struct sw_span *span )
       /* get 32-bit values */
       GLuint zbuffer32[MAX_WIDTH], *zbuffer;
       if (span->arrayMask & SPAN_XY) {
-         rb->GetValues(ctx, rb, count, span->array->x, span->array->y, zbuffer32);
+         _swrast_get_values(ctx, rb, count, span->array->x, span->array->y,
+                            zbuffer32, sizeof(GLuint));
          zbuffer = zbuffer32;
       }
       else {
index 2229e8a..a585615 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5
  *
  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  *
@@ -40,11 +40,6 @@ _swrast_depth_bounds_test( GLcontext *ctx, struct sw_span *span );
 
 
 extern void
-_swrast_read_depth_span( GLcontext *ctx, struct gl_renderbuffer *rb,
-                         GLint n, GLint x, GLint y, GLuint depth[] );
-
-
-extern void
 _swrast_read_depth_span_float( GLcontext *ctx, struct gl_renderbuffer *rb,
                                GLint n, GLint x, GLint y, GLfloat depth[] );
 
index 05e2e0a..ff3c3fc 100644 (file)
@@ -192,7 +192,8 @@ _swrast_logicop_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb,
 
    /* Read dest values from frame buffer */
    if (span->arrayMask & SPAN_XY) {
-      rb->GetValues(ctx, rb, span->end, span->array->x, span->array->y, dest);
+      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+                         dest, sizeof(GLuint));
    }
    else {
       rb->GetRow(ctx, rb, span->end, span->x, span->y, dest);
@@ -218,7 +219,8 @@ _swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
    ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
 
    if (span->arrayMask & SPAN_XY) {
-      rb->GetValues(ctx, rb, span->end, span->array->x, span->array->y, dest);
+      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+                         dest, 4 * sizeof(GLchan));
    }
    else {
       _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y, dest);
index 391dfde..65c4e7d 100644 (file)
@@ -61,7 +61,8 @@ _swrast_mask_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
    ASSERT(span->arrayMask & SPAN_RGBA);
 
    if (span->arrayMask & SPAN_XY) {
-      rb->GetValues(ctx, rb, n, span->array->x, span->array->y, dest);
+      _swrast_get_values(ctx, rb, n, span->array->x, span->array->y,
+                         dest, 4 * sizeof(GLchan));
    }
    else {
       _swrast_read_rgba_span(ctx, rb, n, span->x, span->y, dest);
@@ -134,11 +135,12 @@ _swrast_mask_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb,
    GLuint i;
 
    ASSERT(span->arrayMask & SPAN_INDEX);
-   ASSERT(span->end < MAX_WIDTH);
+   ASSERT(span->end <= MAX_WIDTH);
    ASSERT(rb->DataType == GL_UNSIGNED_INT);
 
    if (span->arrayMask & SPAN_XY) {
-      rb->GetValues(ctx, rb, span->end, span->array->x, span->array->y, dest);
+      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+                         dest, sizeof(GLuint));
    }
    else {
       _swrast_read_index_span(ctx, rb, span->end, span->x, span->y, dest);
index 780f1b6..a9f6684 100644 (file)
@@ -1436,3 +1436,41 @@ _swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
       }
    }
 }
+
+
+/**
+ * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
+ * reading values outside the buffer bounds.
+ * We can use this for reading any format/type of renderbuffer.
+ * \param valueSize is the size in bytes of each value put into the
+ *                  values array.
+ */
+void
+_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
+                   GLuint count, const GLint x[], const GLint y[],
+                   void *values, GLuint valueSize)
+{
+   GLuint i, inCount = 0, inStart = 0;
+
+   for (i = 0; i < count; i++) {
+      if (x[i] >= 0 && y[i] >= 0 && x[i] < rb->Width && y[i] < rb->Height) {
+         /* inside */
+         if (inCount == 0)
+            inStart = i;
+         inCount++;
+      }
+      else {
+         if (inCount > 0) {
+            /* read [inStart, inStart + inCount) */
+            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
+                          (GLubyte *) values + inStart * valueSize);
+            inCount = 0;
+         }
+      }
+   }
+   if (inCount > 0) {
+      /* read last values */
+      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
+                    (GLubyte *) values + inStart * valueSize);
+   }
+}
index 789010b..1bba5aa 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5
  *
  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  *
@@ -67,4 +67,9 @@ extern void
 _swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
                          GLuint n, GLint x, GLint y, GLuint indx[] );
 
+extern void
+_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
+                   GLuint count, const GLint x[], const GLint y[],
+                   void *values, GLuint valueSize);
+
 #endif
index 3e1b287..d8e49cb 100644 (file)
@@ -32,6 +32,7 @@
 #include "s_context.h"
 #include "s_depth.h"
 #include "s_stencil.h"
+#include "s_span.h"
 
 
 
@@ -460,7 +461,7 @@ stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face)
       GLuint i;
 
       /* save the current mask bits */
-      MEMCPY(oldmask, mask, n * sizeof(GLubyte));
+      _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
 
       /* apply the depth test */
       _swrast_depth_test_span(ctx, span);
@@ -913,9 +914,10 @@ stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face )
       GLstencil stencil[MAX_WIDTH];
       GLubyte origMask[MAX_WIDTH];
 
-      rb->GetValues(ctx, rb, n, x, y, stencil);
+      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+      _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
 
-      MEMCPY(origMask, mask, n * sizeof(GLubyte));
+      _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
 
       (void) do_stencil_test(ctx, face, n, stencil, mask);
 
@@ -969,7 +971,7 @@ stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face )
          GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
          GLuint i;
 
-         MEMCPY(oldmask, mask, n * sizeof(GLubyte));
+         _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
 
          _swrast_depth_test_span(ctx, span);