diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2013-08-28 15:36:13 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2013-09-16 16:50:35 -0400 |
commit | f10b5449a8b22a26839c58a716b74d6b7a8bcb80 (patch) | |
tree | fa58bf68f58c9401e2964d108b103e3006f444f5 | |
parent | 700db9d872bdc49399a95565ffe0d345db11717a (diff) |
general: Ensure that iter buffers are aligned to 16 bytes
At the moment iter buffers are only guaranteed to be aligned to a 4
byte boundary. SIMD implementations benefit from the buffers being
aligned to 16 bytes, so ensure this is the case.
V2:
- Use uintptr_t instead of unsigned long
- allocate 3 * SCANLINE_BUFFER_LENGTH byte on stack rather than just
SCANLINE_BUFFER_LENGTH
- use sizeof (stack_scanline_buffer) instead of SCANLINE_BUFFER_LENGTH
to determine overflow
-rw-r--r-- | pixman/pixman-general.c | 22 | ||||
-rw-r--r-- | pixman/pixman-private.h | 3 | ||||
-rw-r--r-- | pixman/pixman-utils.c | 9 |
3 files changed, 27 insertions, 7 deletions
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index 6310bff..a653fa7 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -114,7 +114,7 @@ general_composite_rect (pixman_implementation_t *imp, pixman_composite_info_t *info) { PIXMAN_COMPOSITE_ARGS (info); - uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8]; + uint8_t stack_scanline_buffer[3 * SCANLINE_BUFFER_LENGTH]; uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; uint8_t *src_buffer, *mask_buffer, *dest_buffer; pixman_iter_t src_iter, mask_iter, dest_iter; @@ -137,17 +137,25 @@ general_composite_rect (pixman_implementation_t *imp, Bpp = 16; } - if (width * Bpp > SCANLINE_BUFFER_LENGTH) +#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 (ALIGN (dest_buffer + width * Bpp) > + scanline_buffer + sizeof (stack_scanline_buffer)) { - scanline_buffer = pixman_malloc_abc (width, 3, Bpp); + scanline_buffer = pixman_malloc_ab_plus_c (width, Bpp * 3, 32 * 3); if (!scanline_buffer) return; - } - src_buffer = scanline_buffer; - mask_buffer = src_buffer + width * Bpp; - dest_buffer = 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) { diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 120196d..535117d 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -787,6 +787,9 @@ pixman_malloc_ab (unsigned int n, unsigned int b); void * pixman_malloc_abc (unsigned int a, unsigned int b, unsigned int c); +void * +pixman_malloc_ab_plus_c (unsigned int a, unsigned int b, unsigned int c); + pixman_bool_t _pixman_multiply_overflows_size (size_t a, size_t b); diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c index 98723a8..4a3a835 100644 --- a/pixman/pixman-utils.c +++ b/pixman/pixman-utils.c @@ -49,6 +49,15 @@ _pixman_addition_overflows_int (unsigned int a, unsigned int b) } void * +pixman_malloc_ab_plus_c (unsigned int a, unsigned int b, unsigned int c) +{ + if (!b || a >= INT32_MAX / b || (a * b) > INT32_MAX - c) + return NULL; + + return malloc (a * b + c); +} + +void * pixman_malloc_ab (unsigned int a, unsigned int b) { |