Fix potential segfault when trying to read pixels outside renderbuffer bounds.

Use _swrast_get_values() which does clipping.
This commit is contained in:
Brian Paul 2005-09-16 21:15:27 +00:00
parent 82e314252f
commit 6707433272
8 changed files with 69 additions and 22 deletions

View 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 */

View 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 {

View 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.
*
@ -39,11 +39,6 @@ extern GLboolean
_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[] );

View 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);

View 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);

View 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);
}
}

View 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

View 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);