mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 20:28:04 +02:00
Fix potential segfault when trying to read pixels outside renderbuffer bounds.
Use _swrast_get_values() which does clipping.
This commit is contained in:
parent
82e314252f
commit
6707433272
8 changed files with 69 additions and 22 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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[] );
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue