diff options
author | Pekka Paalanen <pekka.paalanen@collabora.co.uk> | 2015-05-07 16:46:01 +0300 |
---|---|---|
committer | Pekka Paalanen <pekka.paalanen@collabora.co.uk> | 2015-09-01 17:06:46 +0300 |
commit | 13d93aa12050ce99643d56b0c730404294f46c2f (patch) | |
tree | fecef60c6de03b021d6d6a2f56273eb90a0ecf45 | |
parent | c70ddd5c9e12d87ff461d73a6f53b00d52925cf5 (diff) |
utils.[ch]: add fence_image_create_bits ()
Useful for detecting out-of-bounds accesses in composite operations.
This will be used by follow-up patches adding new tests.
Changes in v2:
- fix style on fence_image_create_bits args
- add page to stride only if stride_fence
- add comment on the fallback definition about freeing storage
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Ben Avison <bavison@riscosopen.org>
-rw-r--r-- | test/utils.c | 106 | ||||
-rw-r--r-- | test/utils.h | 6 |
2 files changed, 112 insertions, 0 deletions
diff --git a/test/utils.c b/test/utils.c index e872791..783b97a 100644 --- a/test/utils.c +++ b/test/utils.c @@ -6,6 +6,7 @@ #include <stdlib.h> #include <float.h> #include <ctype.h> +#include <limits.h> #ifdef HAVE_GETTIMEOFDAY #include <sys/time.h> @@ -29,6 +30,8 @@ #include <png.h> #endif +#define ROUND_UP(x, mult) (((x) + (mult) - 1) / (mult) * (mult)) + /* Random number generator state */ @@ -445,6 +448,97 @@ fence_free (void *data) munmap (info->addr, info->n_bytes); } +static void +fence_image_destroy (pixman_image_t *image, void *data) +{ + fence_free (data); +} + +/* Create an image with fence pages. + * + * Creates an image, where the data area is allocated with fence_malloc (). + * Each row has an additional page in the stride. + * + * min_width is only a minimum width for the image. The width is aligned up + * for the row size to be divisible by both page size and pixel size. + * + * If stride_fence is true, the additional page on each row will be armed + * to cause SIGSEVG on all accesses. This should catch all accesses outside + * the valid row pixels. + */ +pixman_image_t * +fence_image_create_bits (pixman_format_code_t format, + int min_width, + int height, + pixman_bool_t stride_fence) +{ + unsigned page_size = getpagesize(); + unsigned page_mask = page_size - 1; + unsigned bitspp = PIXMAN_FORMAT_BPP (format); + unsigned bits_boundary; + unsigned row_bits; + int width; /* pixels */ + unsigned stride; /* bytes */ + void *pixels; + pixman_image_t *image; + int i; + + /* must be power of two */ + assert (page_size && (page_size & page_mask) == 0); + + if (bitspp < 1 || min_width < 1 || height < 1) + abort (); + + /* least common multiple between page size * 8 and bitspp */ + bits_boundary = bitspp; + while (! (bits_boundary & 1)) + bits_boundary >>= 1; + bits_boundary *= page_size * 8; + + /* round up to bits_boundary */ + row_bits = ROUND_UP ( (unsigned)min_width * bitspp, bits_boundary); + width = row_bits / bitspp; + + stride = row_bits / 8; + if (stride_fence) + stride += page_size; /* add fence page */ + + if (UINT_MAX / stride < (unsigned)height) + abort (); + + pixels = fence_malloc (stride * (unsigned)height); + if (!pixels) + return NULL; + + if (stride_fence) + { + uint8_t *guard = (uint8_t *)pixels + stride - page_size; + + /* arm row end fence pages */ + for (i = 0; i < height; i++) + { + if (mprotect (guard + i * stride, page_size, PROT_NONE) == -1) + goto out_fail; + } + } + + assert (width >= min_width); + + image = pixman_image_create_bits_no_clear (format, width, height, + pixels, stride); + if (!image) + goto out_fail; + + pixman_image_set_destroy_function (image, fence_image_destroy, pixels); + + return image; + +out_fail: + fence_free (pixels); + + return NULL; +} + #else /* FENCE_MALLOC_ACTIVE */ void * @@ -459,6 +553,18 @@ fence_free (void *data) free (data); } +pixman_image_t * +fence_image_create_bits (pixman_format_code_t format, + int min_width, + int height, + pixman_bool_t stride_fence) +{ + return pixman_image_create_bits (format, width, height, NULL, 0); + /* Implicitly allocated storage does not need a destroy function + * to get freed on refcount hitting zero. + */ +} + #endif /* FENCE_MALLOC_ACTIVE */ uint8_t * diff --git a/test/utils.h b/test/utils.h index 6018354..5aae554 100644 --- a/test/utils.h +++ b/test/utils.h @@ -106,6 +106,12 @@ fence_malloc (int64_t len); void fence_free (void *data); +pixman_image_t * +fence_image_create_bits (pixman_format_code_t format, + int min_width, + int height, + pixman_bool_t stride_fence); + /* Generate n_bytes random bytes in fence_malloced memory */ uint8_t * make_random_bytes (int n_bytes); |