summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekka Paalanen <pekka.paalanen@collabora.co.uk>2015-05-07 16:46:01 +0300
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>2015-09-01 17:06:46 +0300
commit13d93aa12050ce99643d56b0c730404294f46c2f (patch)
treefecef60c6de03b021d6d6a2f56273eb90a0ecf45
parentc70ddd5c9e12d87ff461d73a6f53b00d52925cf5 (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.c106
-rw-r--r--test/utils.h6
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);