[Mesa-dev] [PATCH 2/8] mesa: add bounds-checking support for client memory buffers

nobled nobled at dreamwidth.org
Tue Apr 19 19:30:16 PDT 2011


This is the first step towards supporting the extension
GL_ARB_robustness.
---
 src/mesa/drivers/dri/intel/intel_pixel_bitmap.c |    2 +-
 src/mesa/drivers/x11/xm_dd.c                    |    6 +-
 src/mesa/main/dlist.c                           |    4 +-
 src/mesa/main/drawpix.c                         |   10 ++--
 src/mesa/main/pbo.c                             |   52 +++++++++++++----------
 src/mesa/main/pbo.h                             |    3 +-
 src/mesa/main/pixel.c                           |    2 +-
 src/mesa/main/readpix.c                         |    2 +-
 src/mesa/main/texgetimage.c                     |    2 +-
 9 files changed, 46 insertions(+), 37 deletions(-)

diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
index 43cdd0d..e59b41d 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
@@ -68,7 +68,7 @@ static const GLubyte *map_pbo( struct gl_context *ctx,

    if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
 				  GL_COLOR_INDEX, GL_BITMAP,
-				  (GLvoid *) bitmap)) {
+				  INT_MAX, (const GLvoid *) bitmap)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
       return NULL;
    }
diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c
index 1369946..81f48f9 100644
--- a/src/mesa/drivers/x11/xm_dd.c
+++ b/src/mesa/drivers/x11/xm_dd.c
@@ -449,7 +449,7 @@ xmesa_DrawPixels_8R8G8B( struct gl_context *ctx,
          /* unpack from PBO */
          GLubyte *buf;
          if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
-                                        format, type, pixels)) {
+                                        format, type, INT_MAX, pixels)) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
                         "glDrawPixels(invalid PBO access)");
             return;
@@ -580,11 +580,11 @@ xmesa_DrawPixels_5R6G5B( struct gl_context *ctx,
       if (swrast->NewState)
          _swrast_validate_derived( ctx );

-      if (unpack->BufferObj->Name) {
+      if (_mesa_is_bufferobj(unpack->BufferObj)) {
          /* unpack from PBO */
          GLubyte *buf;
          if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
-                                        format, type, pixels)) {
+                                        format, type, INT_MAX, pixels)) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
                         "glDrawPixels(invalid PBO access)");
             return;
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index f66082e..63653df 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -859,8 +859,8 @@ unpack_image(struct gl_context *ctx, GLuint dimensions,
       }
       return image;
    }
-   else if (_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
-                                      format, type, pixels)) {
+   else if (_mesa_validate_pbo_access(dimensions, unpack, width, height,
+                                      depth, format, type, INT_MAX, pixels)) {
       const GLubyte *map, *src;
       GLvoid *image;

diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c
index a8b948d..89c2b26 100644
--- a/src/mesa/main/drawpix.c
+++ b/src/mesa/main/drawpix.c
@@ -92,8 +92,8 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,

          if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
             /* unpack from PBO */
-            if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
-                                           format, type, pixels)) {
+            if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
+                                           1, format, type, INT_MAX, pixels)) {
                _mesa_error(ctx, GL_INVALID_OPERATION,
                            "glDrawPixels(invalid PBO access)");
                goto end;
@@ -251,9 +251,9 @@ _mesa_Bitmap( GLsizei width, GLsizei height,

          if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
             /* unpack from PBO */
-            if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
-                                           GL_COLOR_INDEX, GL_BITMAP,
-                                           (GLvoid *) bitmap)) {
+            if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
+                                           1, GL_COLOR_INDEX, GL_BITMAP,
+                                           INT_MAX, (const GLvoid *) bitmap)) {
                _mesa_error(ctx, GL_INVALID_OPERATION,
                            "glBitmap(invalid PBO access)");
                return;
diff --git a/src/mesa/main/pbo.c b/src/mesa/main/pbo.c
index 56b26a9..0a686db 100644
--- a/src/mesa/main/pbo.c
+++ b/src/mesa/main/pbo.c
@@ -43,7 +43,7 @@
  * When we're about to read pixel data out of a PBO (via glDrawPixels,
  * glTexImage, etc) or write data into a PBO (via glReadPixels,
  * glGetTexImage, etc) we call this function to check that we're not
- * going to read out of bounds.
+ * going to read/write out of bounds.
  *
  * XXX This would also be a convenient time to check that the PBO isn't
  * currently mapped.  Whoever calls this function should check for that.
@@ -56,43 +56,52 @@
  * \param depth  depth of image to read/write
  * \param format  format of image to read/write
  * \param type  datatype of image to read/write
+ * \param clientMemSize  the maximum number of bytes to read/write
  * \param ptr  the user-provided pointer/offset
- * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would
+ * \return GL_TRUE if the buffer access is OK, GL_FALSE if the access would
  *         go out of bounds.
  */
 GLboolean
 _mesa_validate_pbo_access(GLuint dimensions,
                           const struct gl_pixelstore_attrib *pack,
                           GLsizei width, GLsizei height, GLsizei depth,
-                          GLenum format, GLenum type, const GLvoid *ptr)
+                          GLenum format, GLenum type, GLsizei clientMemSize,
+                          const GLvoid *ptr)
 {
-   GLvoid *start, *end;
+   const GLvoid *start, *end, *offset;
    const GLubyte *sizeAddr; /* buffer size, cast to a pointer */

-   if (!_mesa_is_bufferobj(pack->BufferObj))
-      return GL_TRUE;  /* no PBO, OK */
+   /* If no PBO is bound, 'ptr' is a pointer to client memory containing
+      'clientMemSize' bytes.
+      If a PBO is bound, 'ptr' is an offset into the bound PBO.
+      In that case 'clientMemSize' is ignored: we just use the PBO's size.
+    */
+   if (!_mesa_is_bufferobj(pack->BufferObj)) {
+      offset = 0;
+      sizeAddr = ((const GLubyte *) 0) + clientMemSize;
+   } else {
+      offset = ptr;
+      sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
+   }

-   if (pack->BufferObj->Size == 0)
+   if (sizeAddr == 0)
       /* no buffer! */
       return GL_FALSE;

-   /* get address of first pixel we'll read */
-   start = _mesa_image_address(dimensions, pack, ptr, width, height,
+   /* get the offset to the first pixel we'll read/write */
+   start = _mesa_image_address(dimensions, pack, offset, width, height,
                                format, type, 0, 0, 0);

-   /* get address just past the last pixel we'll read */
-   end = _mesa_image_address(dimensions, pack, ptr, width, height,
-                             format, type, depth-1, height-1, width);
-
-
-   sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
+   /* get the offset to just past the last pixel we'll read/write */
+   end =  _mesa_image_address(dimensions, pack, offset, width, height,
+                              format, type, depth-1, height-1, width);

    if ((const GLubyte *) start > sizeAddr) {
       /* This will catch negative values / wrap-around */
       return GL_FALSE;
    }
    if ((const GLubyte *) end > sizeAddr) {
-      /* Image read goes beyond end of buffer */
+      /* Image read/write goes beyond end of buffer */
       return GL_FALSE;
    }

@@ -159,8 +168,8 @@ _mesa_map_validate_pbo_source(struct gl_context *ctx,
       return ptr;
    }

-   if (!_mesa_validate_pbo_access(dimensions, unpack,
-                                  width, height, depth, format, type, ptr)) {
+   if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
+                                     format, type, INT_MAX, ptr)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(out of bounds PBO access)", where);
       return NULL;
@@ -249,8 +258,8 @@ _mesa_map_validate_pbo_dest(struct gl_context *ctx,
       return ptr;
    }

-   if (!_mesa_validate_pbo_access(dimensions, unpack,
-                                  width, height, depth, format, type, ptr)) {
+   if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
+                                  format, type, INT_MAX, ptr)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(out of bounds PBO access)", where);
       return NULL;
@@ -281,7 +290,6 @@ _mesa_unmap_pbo_dest(struct gl_context *ctx,
 }


-
 /**
  * Check if an unpack PBO is active prior to fetching a texture image.
  * If so, do bounds checking and map the buffer into main memory.
@@ -302,7 +310,7 @@ _mesa_validate_pbo_teximage(struct gl_context
*ctx, GLuint dimensions,
       return pixels;
    }
    if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
-                                  format, type, pixels)) {
+                                     format, type, INT_MAX, pixels)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)");
       return NULL;
    }
diff --git a/src/mesa/main/pbo.h b/src/mesa/main/pbo.h
index 0cddd72..17039cf 100644
--- a/src/mesa/main/pbo.h
+++ b/src/mesa/main/pbo.h
@@ -34,7 +34,8 @@ extern GLboolean
 _mesa_validate_pbo_access(GLuint dimensions,
                           const struct gl_pixelstore_attrib *pack,
                           GLsizei width, GLsizei height, GLsizei depth,
-                          GLenum format, GLenum type, const GLvoid *ptr);
+                          GLenum format, GLenum type, GLsizei clientMemSize,
+                          const GLvoid *ptr);

 extern const GLvoid *
 _mesa_map_pbo_source(struct gl_context *ctx,
diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c
index da99c9b..6e4ed99 100644
--- a/src/mesa/main/pixel.c
+++ b/src/mesa/main/pixel.c
@@ -157,7 +157,7 @@ validate_pbo_access(struct gl_context *ctx, struct
gl_pixelstore_attrib *pack,
                                  pack->BufferObj);

    ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
-                                  format, type, ptr);
+                                  format, type, INT_MAX, ptr);

    /* restore */
    _mesa_reference_buffer_object(ctx,
diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c
index a172a00..fd6752b 100644
--- a/src/mesa/main/readpix.c
+++ b/src/mesa/main/readpix.c
@@ -226,7 +226,7 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width,
GLsizei height,

    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
       if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
-                                     format, type, pixels)) {
+                                     format, type, 0, pixels)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glReadPixels(invalid PBO access)");
          return;
diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c
index 7070a29..79af23f 100644
--- a/src/mesa/main/texgetimage.c
+++ b/src/mesa/main/texgetimage.c
@@ -735,7 +735,7 @@ getteximage_error_check(struct gl_context *ctx,
GLenum target, GLint level,
       const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
       if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
                                      texImage->Height, texImage->Depth,
-                                     format, type, pixels)) {
+                                     format, type, INT_MAX, pixels)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glGetTexImage(out of bounds PBO write)");
          return GL_TRUE;
-- 
1.7.0.4


More information about the mesa-dev mailing list