pixman: Branch 'master' - 2 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Wed May 21 15:10:31 PDT 2014


 pixman/pixman-gradient-walker.c |    2 -
 pixman/pixman-private.h         |    4 +-
 test/Makefile.sources           |    1 
 test/radial-invalid.c           |   54 ++++++++++++++++++++++++++++++++++++++++
 test/utils.c                    |   10 +++++++
 test/utils.h                    |    1 
 6 files changed, 69 insertions(+), 3 deletions(-)

New commits:
commit 9cd283b2eb8279824406bfd47b020d21fc00cf82
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Wed Apr 23 20:25:40 2014 -0400

    pixman-gradient-walker: Make left_x and right_x 64 bit variables
    
    The variables left_x, and right_x in gradient_walker_reset() are
    computed from pos, which is a 64 bit quantity, so to avoid overflows,
    these variables must be 64 bit as well.
    
    Similarly, the left_x and right_x that are stored in
    pixman_gradient_walker_t need to be 64 bit as well; otherwise,
    pixman_gradient_walker_pixel() will call reset too often.
    
    This fixes the radial-invalid test, which was generating 'invalid'
    floating point exceptions when the overflows caused color values to be
    outside of [0, 255].

diff --git a/pixman/pixman-gradient-walker.c b/pixman/pixman-gradient-walker.c
index 5944a55..822f8e6 100644
--- a/pixman/pixman-gradient-walker.c
+++ b/pixman/pixman-gradient-walker.c
@@ -54,7 +54,7 @@ static void
 gradient_walker_reset (pixman_gradient_walker_t *walker,
 		       pixman_fixed_48_16_t      pos)
 {
-    int32_t x, left_x, right_x;
+    int64_t x, left_x, right_x;
     pixman_color_t *left_c, *right_c;
     int n, count = walker->num_stops;
     pixman_gradient_stop_t *stops = walker->stops;
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 6ca13b2..fdc966a 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -345,8 +345,8 @@ typedef struct
     float		    r_s, r_b;
     float		    g_s, g_b;
     float		    b_s, b_b;
-    pixman_fixed_t	    left_x;
-    pixman_fixed_t          right_x;
+    pixman_fixed_48_16_t    left_x;
+    pixman_fixed_48_16_t    right_x;
 
     pixman_gradient_stop_t *stops;
     int                     num_stops;
commit f5f5dbbbc668a3a90c6cfc79bbd2422805db31e7
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date:   Wed Apr 23 20:07:37 2014 -0400

    test: Add radial-invalid test program
    
    This program demonstrates a bug in gradient walker, where some integer
    overflows cause colors outside the range [0, 255] to be generated,
    which in turns cause 'invalid' floating point exceptions when those
    colors are converted to uint8_t.
    
    The bug was first reported by Owen Taylor on the #cairo IRC channel.

diff --git a/test/Makefile.sources b/test/Makefile.sources
index 9b520ec..c7f1657 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -2,6 +2,7 @@
 TESTPROGRAMS =			\
 	prng-test		\
 	a1-trap-test		\
+	radial-invalid		\
 	pdf-op-test		\
 	region-test		\
 	region-translate-test	\
diff --git a/test/radial-invalid.c b/test/radial-invalid.c
new file mode 100644
index 0000000..ec85fe3
--- /dev/null
+++ b/test/radial-invalid.c
@@ -0,0 +1,54 @@
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "utils.h"
+
+#define WIDTH 100
+#define HEIGHT 100
+
+int
+main ()
+{
+    pixman_image_t *radial;
+    pixman_image_t *dest = pixman_image_create_bits (
+	PIXMAN_a8r8g8b8, WIDTH, HEIGHT, NULL, -1);
+
+    static const pixman_transform_t xform =
+	{
+	    { { 0x346f7, 0x0, 0x0 },
+	      { 0x0, 0x346f7, 0x0 },
+	      { 0x0, 0x0, 0x10000 }
+	    },
+	};
+
+    static const pixman_gradient_stop_t stops[] = 
+    {
+	{ 0xde61, { 0x4481, 0x96e8, 0x1e6a, 0x29e1 } },
+	{ 0xfdd5, { 0xfa10, 0xcc26, 0xbc43, 0x1eb7 } },
+	{ 0xfe1e, { 0xd257, 0x5bac, 0x6fc2, 0xa33b } },
+    };
+
+    static const pixman_point_fixed_t inner = { 0x320000, 0x320000 };
+    static const pixman_point_fixed_t outer = { 0x320000, 0x3cb074 };
+
+    enable_divbyzero_exceptions ();
+    enable_invalid_exceptions ();
+
+    radial = pixman_image_create_radial_gradient (
+	&inner,
+	&outer,
+	0xab074, /* inner radius */
+	0x0,	 /* outer radius */
+	stops, sizeof (stops) / sizeof (stops[0]));
+
+    pixman_image_set_repeat (radial, PIXMAN_REPEAT_REFLECT);
+    pixman_image_set_transform (radial, &xform);
+
+    pixman_image_composite (
+	PIXMAN_OP_OVER,
+	radial, NULL, dest,
+	0, 0, 0, 0,
+	0, 0, WIDTH, HEIGHT);
+
+    return 0;
+}
diff --git a/test/utils.c b/test/utils.c
index 1888417..ab3424f 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -849,6 +849,16 @@ enable_divbyzero_exceptions (void)
 #endif
 }
 
+void
+enable_invalid_exceptions (void)
+{
+#ifdef HAVE_FENV_H
+#ifdef HAVE_FEENABLEEXCEPT
+    feenableexcept (FE_INVALID);
+#endif
+#endif
+}
+
 void *
 aligned_malloc (size_t align, size_t size)
 {
diff --git a/test/utils.h b/test/utils.h
index ebb14d9..6804334 100644
--- a/test/utils.h
+++ b/test/utils.h
@@ -120,6 +120,7 @@ fail_after (int seconds, const char *msg);
 
 /* If possible, enable traps for floating point exceptions */
 void enable_divbyzero_exceptions(void);
+void enable_invalid_exceptions(void);
 
 /* Converts a8r8g8b8 pixels to pixels that
  *  - are not premultiplied,


More information about the xorg-commit mailing list