test: Add radial-invalid test program
authorSøren Sandmann Pedersen <ssp@redhat.com>
Thu, 24 Apr 2014 00:07:37 +0000 (20:07 -0400)
committerSøren Sandmann <ssp@redhat.com>
Thu, 15 May 2014 17:29:38 +0000 (13:29 -0400)
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.

test/Makefile.sources
test/radial-invalid.c [new file with mode: 0644]
test/utils.c
test/utils.h

index 9b520ec..c7f1657 100644 (file)
@@ -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 (file)
index 0000000..ec85fe3
--- /dev/null
@@ -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;
+}
index 1888417..ab3424f 100644 (file)
@@ -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)
 {
index ebb14d9..6804334 100644 (file)
@@ -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,