summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiarhei Siamashka <siarhei.siamashka@gmail.com>2015-09-22 04:25:40 +0300
committerOded Gabbay <oded.gabbay@gmail.com>2015-09-22 13:19:06 +0300
commit8b49d4b6b460d0c9299bca4ccddd7cd00d8f8441 (patch)
tree311b374cd4baf19219509dd137dd102b2ba31021
parent4297e9058d252cac653723fe0b1bee559fbac3a4 (diff)
pixman-general: Fix stack related pointer arithmetic overflow
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 <ludo@gnu.org> Signed-off-by: Siarhei Siamashka <siarhei.siamashka@gmail.com> Reviewed-by: soren.sandmann@gmail.com Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
-rw-r--r--pixman/pixman-general.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 7cdea29..fa88463 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -155,23 +155,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 */