From 67074332728acba86da7630353673b458713bb8a Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 16 Sep 2005 21:15:27 +0000 Subject: [PATCH] Fix potential segfault when trying to read pixels outside renderbuffer bounds. Use _swrast_get_values() which does clipping. --- src/mesa/swrast/s_blend.c | 4 ++-- src/mesa/swrast/s_depth.c | 11 +++++++---- src/mesa/swrast/s_depth.h | 7 +------ src/mesa/swrast/s_logic.c | 6 ++++-- src/mesa/swrast/s_masking.c | 8 +++++--- src/mesa/swrast/s_span.c | 38 +++++++++++++++++++++++++++++++++++++ src/mesa/swrast/s_span.h | 7 ++++++- src/mesa/swrast/s_stencil.c | 10 ++++++---- 8 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/mesa/swrast/s_blend.c b/src/mesa/swrast/s_blend.c index d34ecacbb23..d94ff3923cf 100644 --- a/src/mesa/swrast/s_blend.c +++ b/src/mesa/swrast/s_blend.c @@ -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 */ diff --git a/src/mesa/swrast/s_depth.c b/src/mesa/swrast/s_depth.c index 54aa040d576..c70fdeabb5a 100644 --- a/src/mesa/swrast/s_depth.c +++ b/src/mesa/swrast/s_depth.c @@ -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 { diff --git a/src/mesa/swrast/s_depth.h b/src/mesa/swrast/s_depth.h index 2229e8a22df..a5856151f06 100644 --- a/src/mesa/swrast/s_depth.h +++ b/src/mesa/swrast/s_depth.h @@ -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[] ); diff --git a/src/mesa/swrast/s_logic.c b/src/mesa/swrast/s_logic.c index 05e2e0ade47..ff3c3fc2f14 100644 --- a/src/mesa/swrast/s_logic.c +++ b/src/mesa/swrast/s_logic.c @@ -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); diff --git a/src/mesa/swrast/s_masking.c b/src/mesa/swrast/s_masking.c index 391dfde7a19..65c4e7d01cc 100644 --- a/src/mesa/swrast/s_masking.c +++ b/src/mesa/swrast/s_masking.c @@ -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); diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index 780f1b63990..a9f6684a72b 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -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); + } +} diff --git a/src/mesa/swrast/s_span.h b/src/mesa/swrast/s_span.h index 789010bd7fc..1bba5aa53b3 100644 --- a/src/mesa/swrast/s_span.h +++ b/src/mesa/swrast/s_span.h @@ -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 diff --git a/src/mesa/swrast/s_stencil.c b/src/mesa/swrast/s_stencil.c index 3e1b28740a8..d8e49cbe415 100644 --- a/src/mesa/swrast/s_stencil.c +++ b/src/mesa/swrast/s_stencil.c @@ -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); -- 2.30.2