From 204fcd24d9b7e3988b7496e723014f327828751a Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Tue, 22 Sep 2015 04:25:40 +0300 Subject: pixman-general: Fix stack related pointer arithmetic overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As https://bugs.freedesktop.org/show_bug.cgi?id=92027#c6 explains, the stack is allocated at the very top of the process address space in some configurations (32-bit x86 systems with ASLR disabled). And the careless computations done with the 'dest_buffer' pointer may overflow, failing the buffer upper limit check. The problem can be reproduced using the 'stress-test' program, which segfaults when executed via setarch: export CFLAGS="-O2 -m32" && ./autogen.sh ./configure --disable-libpng --disable-gtk && make setarch i686 -R test/stress-test This patch introduces the required corrections. The extra check for negative 'width' may be redundant (the invalid 'width' value is not supposed to reach here), but it's better to play safe when dealing with the buffers allocated on stack. Reported-by: Ludovic Courtès Signed-off-by: Siarhei Siamashka Reviewed-by: soren.sandmann@gmail.com Signed-off-by: Oded Gabbay --- pixman/pixman-general.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index a653fa7..f82ea7d 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -140,23 +140,21 @@ general_composite_rect (pixman_implementation_t *imp, #define ALIGN(addr) \ ((uint8_t *)((((uintptr_t)(addr)) + 15) & (~15))) - src_buffer = ALIGN (scanline_buffer); - mask_buffer = ALIGN (src_buffer + width * Bpp); - dest_buffer = ALIGN (mask_buffer + width * Bpp); + if (width <= 0 || _pixman_multiply_overflows_int (width, Bpp * 3)) + return; - if (ALIGN (dest_buffer + width * Bpp) > - scanline_buffer + sizeof (stack_scanline_buffer)) + if (width * Bpp * 3 > sizeof (stack_scanline_buffer) - 32 * 3) { scanline_buffer = pixman_malloc_ab_plus_c (width, Bpp * 3, 32 * 3); if (!scanline_buffer) return; - - src_buffer = ALIGN (scanline_buffer); - mask_buffer = ALIGN (src_buffer + width * Bpp); - dest_buffer = ALIGN (mask_buffer + width * Bpp); } + src_buffer = ALIGN (scanline_buffer); + mask_buffer = ALIGN (src_buffer + width * Bpp); + dest_buffer = ALIGN (mask_buffer + width * Bpp); + if (width_flag == ITER_WIDE) { /* To make sure there aren't any NANs in the buffers */ -- cgit v1.2.3