[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