pixman: Branch 'master' - 2 commits
Søren Sandmann Pedersen
sandmann at kemper.freedesktop.org
Mon Aug 16 03:30:08 PDT 2010
configure.ac | 12 +++++++++++-
pixman/pixman-image.c | 27 +++++++++++++++++++++++++++
pixman/pixman-private.h | 1 +
test/Makefile.am | 4 ++++
test/alpha-loop.c | 29 +++++++++++++++++++++++++++++
test/utils.c | 33 +++++++++++++++++++++++++++++++++
test/utils.h | 3 +++
7 files changed, 108 insertions(+), 1 deletion(-)
New commits:
commit 4e5d6f00bf409259ff6f5d5c3ef4b016146bcbb3
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Wed Aug 4 17:51:49 2010 -0400
pixman_image_set_alpha_map(): Disallow alpha map cycles
If someone tries to set an alpha map that itself has an alpha map,
simply return. Also, if someone tries to add an alpha map to an image
that is being _used_ as an alpha map, simply return.
This ensures that an alpha map can never have an alpha map.
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 269c3c1..cdc9c40 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -101,6 +101,7 @@ _pixman_image_allocate (void)
pixman_region32_init (&common->clip_region);
+ common->alpha_count = 0;
common->have_clip_region = FALSE;
common->clip_sources = FALSE;
common->transform = NULL;
@@ -668,15 +669,41 @@ pixman_image_set_alpha_map (pixman_image_t *image,
return_if_fail (!alpha_map || alpha_map->type == BITS);
+ if (alpha_map && common->alpha_count > 0)
+ {
+ /* If this image is being used as an alpha map itself,
+ * then you can't give it an alpha map of its own.
+ */
+ return;
+ }
+
+ if (alpha_map && alpha_map->common.alpha_map)
+ {
+ /* If the image has an alpha map of its own,
+ * then it can't be used as an alpha map itself
+ */
+ return;
+ }
+
if (common->alpha_map != (bits_image_t *)alpha_map)
{
if (common->alpha_map)
+ {
+ common->alpha_map->common.alpha_count--;
+
pixman_image_unref ((pixman_image_t *)common->alpha_map);
+ }
if (alpha_map)
+ {
common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
+
+ common->alpha_map->common.alpha_count++;
+ }
else
+ {
common->alpha_map = NULL;
+ }
}
common->alpha_origin_x = x;
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 0629c42..c4e6bb8 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -80,6 +80,7 @@ struct image_common
image_type_t type;
int32_t ref_count;
pixman_region32_t clip_region;
+ int32_t alpha_count; /* How many times this image is being used as an alpha map */
pixman_bool_t have_clip_region; /* FALSE if there is no clip */
pixman_bool_t client_clip; /* Whether the source clip was
set by a client */
commit 9fe7d32c4b704a10e780444530eaea28b4351110
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Wed Aug 4 17:55:14 2010 -0400
Add alpha-loop test program
This tests what happens if you attempt to make an image with an alpha
map that has the image as its alpha map. This results in an infinite
loop in _pixman_image_validate(), so the test sets up a SIGALRM to
exit if it runs for more than five seconds.
diff --git a/configure.ac b/configure.ac
index 98c2783..acec8a1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -600,13 +600,23 @@ AC_SUBST(DEP_CFLAGS)
AC_SUBST(DEP_LIBS)
dnl =====================================
-dnl posix_memalign
+dnl posix_memalign, sigaction, alarm
AC_CHECK_FUNC(posix_memalign, have_posix_memalign=yes, have_posix_memalign=no)
if test x$have_posix_memalign = xyes; then
AC_DEFINE(HAVE_POSIX_MEMALIGN, 1, [Whether we have posix_memalign()])
fi
+AC_CHECK_FUNC(sigaction, have_sigaction=yes, have_sigaction=no)
+if test x$have_sigaction = xyes; then
+ AC_DEFINE(HAVE_SIGACTION, 1, [Whether we have sigaction()])
+fi
+
+AC_CHECK_FUNC(alarm, have_alarm=yes, have_alarm=no)
+if test x$have_alarm = xyes; then
+ AC_DEFINE(HAVE_ALARM, 1, [Whether we have alarm()])
+fi
+
dnl =====================================
dnl Thread local storage
diff --git a/test/Makefile.am b/test/Makefile.am
index 2a7aea2..5273bec 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -13,6 +13,7 @@ TESTPROGRAMS = \
gradient-crash-test \
trap-crasher \
alphamap \
+ alpha-loop \
scaling-crash-test \
blitters-test \
scaling-test \
@@ -39,6 +40,9 @@ scaling_test_SOURCES = scaling-test.c utils.c utils.h
alphamap_LDADD = $(TEST_LDADD)
alphamap_SOURCES = alphamap.c utils.c utils.h
+alpha_loop_LDADD = $(TEST_LDADD)
+alpha_loop_SOURCES = alpha-loop.c utils.c utils.h
+
# GTK using test programs
if HAVE_GTK
diff --git a/test/alpha-loop.c b/test/alpha-loop.c
new file mode 100644
index 0000000..e4d90a9
--- /dev/null
+++ b/test/alpha-loop.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "utils.h"
+
+#define WIDTH 400
+#define HEIGHT 200
+
+int
+main (int argc, char **argv)
+{
+ uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT);
+ uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4);
+ uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4);
+
+ pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH);
+ pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4);
+ pixman_image_t *s = pixman_image_create_bits (PIXMAN_a2r10g10b10, WIDTH, HEIGHT, src, WIDTH * 4);
+
+ fail_after (5, "Infinite loop detected: 5 seconds without progress\n");
+
+ pixman_image_set_alpha_map (s, a, 0, 0);
+ pixman_image_set_alpha_map (a, s, 0, 0);
+
+ pixman_image_composite (PIXMAN_OP_SRC, s, NULL, d, 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+
+ pixman_image_unref (s);
+
+ return 0;
+}
diff --git a/test/utils.c b/test/utils.c
index 1ee5c9c..d95cbc2 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -1,4 +1,9 @@
#include "utils.h"
+#include <signal.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
/* Random number seed
*/
@@ -319,3 +324,31 @@ fuzzer_test_main (const char *test_name,
return 0;
}
+
+static const char *global_msg;
+
+static void
+on_alarm (int signo)
+{
+ printf ("%s\n", global_msg);
+ exit (1);
+}
+
+void
+fail_after (int seconds, const char *msg)
+{
+#ifdef HAVE_SIGACTION
+#ifdef HAVE_ALARM
+ struct sigaction action;
+
+ global_msg = msg;
+
+ memset (&action, 0, sizeof (action));
+ action.sa_handler = on_alarm;
+
+ alarm (seconds);
+
+ sigaction (SIGALRM, &action, NULL);
+#endif
+#endif
+}
diff --git a/test/utils.h b/test/utils.h
index 95d809a..bfb76a5 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -62,3 +62,6 @@ fuzzer_test_main (const char *test_name,
uint32_t (*test_function)(int testnum, int verbose),
int argc,
const char *argv[]);
+
+void
+fail_after (int seconds, const char *msg);
More information about the xorg-commit
mailing list