diff options
author | Siarhei Siamashka <siarhei.siamashka@gmail.com> | 2015-09-22 04:25:40 +0300 |
---|---|---|
committer | Oded Gabbay <oded.gabbay@gmail.com> | 2015-09-22 13:19:06 +0300 |
commit | 8b49d4b6b460d0c9299bca4ccddd7cd00d8f8441 (patch) | |
tree | 311b374cd4baf19219509dd137dd102b2ba31021 | |
parent | 4297e9058d252cac653723fe0b1bee559fbac3a4 (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.c | 16 |
1 files changed, 7 insertions, 9 deletions
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index 7cdea295..fa88463c 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 */ |