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